TraceLocationというgemを使ってみた!
ツイッターを見ていたら、カルパスさんがコードリーディング用のgemを作ったという情報をgetしたので、早速試してみました!!1
以下はそのリポジトリです!
こちらのスライドで、どういう思いで作ったのか・どう使うのかについて書いてくださっております!!
使ってみる!
昔railsを使って作成したブログアプリの中にTraceLocationを入れてみました!
①gemfileのなかに、gem 'trace_location' を書いてbundle installします。
②コンソールを立ち上げ、env = Rack::MockRequest.env_for('http://localhost:3000/api/stories') を実行します。
~/p/r/blog3 (master|✚2) $ rails c
Running via Spring preloader in process 3478
Loading development environment (Rails 5.2.2)
[1] pry(main)> env = Rack::MockRequest.env_for('http://localhost:3000/api/stories')
=> {"rack.version"=>[1, 3],
"rack.input"=>#<StringIO:0x00007fc82759a258>,
"rack.errors"=>#<StringIO:0x00007fc82759a4d8>,
"rack.multithread"=>true,
"rack.multiprocess"=>true,
"rack.run_once"=>false,
"REQUEST_METHOD"=>"GET",
"SERVER_NAME"=>"localhost",
"SERVER_PORT"=>"3000",
"QUERY_STRING"=>"",
"PATH_INFO"=>"/api/stories",
"rack.url_scheme"=>"http",
"HTTPS"=>"off",
"SCRIPT_NAME"=>"",
"CONTENT_LENGTH"=>"0"}
②TraceLocation.trace { status, headers, body = Rails.application.call(env) } を実行します。
[2] pry(main)> TraceLocation.trace { status, headers, body = Rails.application.call(env) }
Started GET "/api/stories" for at 2019-05-02 22:23:16 +0900
Cannot render console from ! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
(59.1ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
(5.4ms) SELECT `schema_migrations`.`version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` ASC
ActionController::RoutingError (No route matches [GET] "/api/stories"):
(pry):2:in `block in __pry__'
(pry):2:in `__pry__'
Created at /Users/hayashiyoshino/projects/rails-projects/blog3/log/trace_location-2019050222051556803399.log
=> true
③/log/trace_location-2019050222051556803399.log ファイルを見にいきます。
すると、以下の画像のように、どのディレクトリに・ファイル名・何行目のメソッドが呼ばれたかが書かれているログがみれます!
④ログの情報を元にソースコードを追ってみます。
/Users/hayashiyoshino/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/railties-5.2.2/lib/rails.rb:39#application
を開いてみると、以下のようなメソッドが呼ばれておりました!
def application
@application ||= (app_class.instance if app_class)
end
次のログも同じように、
C /Users/hayashiyoshino/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/railties-5.2.2/lib/rails/engine.rb:522#call
を開いてみると、以下のようなメソッドが呼ばれていることがわかりました!!
def call(env)
req = build_request env
app.call req.env
end
そしてcallメソッドの中で呼ばれている build_request メソッドは
C /Users/hayashiyoshino/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/railties-5.2.2/lib/rails/application.rb:591#build_request
にあるようです!!
def build_request(env)
req = super
env["ORIGINAL_FULLPATH"] = req.fullpath
env["ORIGINAL_SCRIPT_NAME"] = req.script_name
req
end
感想その他
Rubymineのジャンプ機能を以ってしても迷子になる&人から解説してもらっても所々抜けてしまう自分にとって、とても有難いgemでした!!
コードを追いかけるべき順番と場所がこのようにこまかーーく出てくれているのは有難いです!!
迷子にならずコードを追えるのは非常に快適です!!
それと、以下のツイートでカルパスさんがおっしゃっていたように、bootsnapのログが沢山出るので、コードリーディングするときはbootsnapを呼ばれないようにするのが良さそうです!
いま見返すと、レスポンスがreturnされているところもキャプで出すべきだったなと反省してる。そこまでの一連の動作がわかって、有用性が感じられると思うので、ちょっと失敗した。学習的に読む場合は、bootsnapをOFFにした方がログの分量が増えないので、外してからログを出すといいかもしれない。
— カルパス (@yoshi_hirano) May 2, 2019
コードリーディングやってゆきます!!