gemのソースを pry-byebug を使ってブレークポイントで止めて読む準備
いつも仕事でもプライベートでも使っている bundler だけど、中身のコードを把握していないのでどうも雰囲気で使っている感が否めない。
そこで、ソースを読み腹落ち感を得るためにコードを読む準備を進めてみた。
pry-byebug を使ってブレークポイントで止められるようにする
(1). システムに pry-byebugを入れる
毎回 Gemfile 書くのは面倒なのでシステムに入れちゃう
gem install pry-byebug gem install pry-stack_explorer # 超便利なのでこれも
(2). require "pry" して、止めたいところで binding.pryすれば止まる
require "pry" ar = [1,2,3] ar.each do |i| binding.pry # ここで止まる p i end
便利。
bundlerのコードで試してみる
(1). ソースを git cloneする
$ git clone git@github.com:bundler/bundler.git ~/src
/vendor/bundle に入ったコードだと git blame できなくて普通に読みづらいので、git clone したり gem-src を使うなりして git repository を取得した方が良い。
(2). CUI ツールのエントリポイントであるbundler/exe/bundle でまずは require "pry"する
#!/usr/bin/env ruby # frozen_string_literal: true require 'pry' (略
(3). 実行して止まるか確認
./bundler で実行すればシステムに入っている方ではなく git clone した方の bundler が実行できる。
$ cd /Users/suzuki_y/src/bundler/exe/ suzuki_y@MBP:~/s/b/exe$ ./bundle install From: /Users/suzuki_y/src/bundler/exe/bundle @ line 30 : 25: require "bundler/cli" 26: 27: binding.pry 28: 29: # Allow any command to use --help flag to show help for that command => 30: help_flags = %w[--help -h] 31: help_flag_used = ARGV.any? {|a| help_flags.include? a } 32: args = help_flag_used ? Bundler::CLI.reformatted_help_args(ARGV) : ARGV 33: 34: Bundler::CLI.start(args, :debug => true) 35: end [1] pry(main)>
無事止まりました。
show-stackでコールスタックもみれます。
[1] pry(main)> show-stack Showing all accessible frames in stack (9 in total): -- => #0 <main> #1 [block] block in run <Byebug::PryProcessor#run(&_block)> #2 [method] run <Byebug::PryProcessor#run(&_block)> #3 [method] resume_pry <Byebug::PryProcessor#resume_pry()> #4 [method] at_line <Byebug::PryProcessor#at_line()> #5 [method] at_line <Byebug::Context#at_line()> #6 [block] block in <main> #7 [method] with_friendly_errors <Bundler.with_friendly_errors()> #8 [main] <main>
あとは、コードを好きにいじりながら自由にコード読み放題です。
メソッド系のgemの場合
また、 bundlerのようなコマンド系の gem ではなく、tapp gem のようにコード内で使用するメソッド系の gem は、
gemのルートディレクトリに main.rb みたいな適当なファイルを作って、そこから対象のgemを require して呼び出しを行ってとっかかりを作ります。
# src/tapp/main.rb require "./lib/tapp" require "pry" binding.pry "123".tapp "123".taputs
From: /Users/suzuki_y/src/tapp/main.rb @ line 6 : 1: require "./lib/tapp" 2: require "pry" 3: 4: binding.pry 5: => 6: "123".tapp 7: "123".taputs [1] pry(main)> step From: /Users/suzuki_y/src/tapp/lib/tapp.rb @ line 13 Tapp.config: 12: def config => 13: @config ||= Tapp::Configuration.new 14: end [1] pry(Tapp):1>
いい感じですね。
RubyMineを使ったやり方もあとで追記したいと思います。