SlideShare a Scribd company logo
Predefを使ったSQLのトレース
山本悠滋
2015-06-04 表参道.rb #1
こんにちは!
山本悠滋(@igrep) 26歳♂
Eightのサーバーサイド担当です。
最近はCoffeeScriptでクライアントをよく触ります。
Haskellの勉強会を毎月やっとります。
小さな小さなgemを作りました
predefと言います
小さな小さなgemを作りました
使ったことある人ー ( ^ω^)ノ
小さな小さなgemを作りました
リリースまだですけどwww
=> しました! predef
なにするgem?
「Module#prependしてdefするgem」略して「predef」
ただのModule#prependのショートカット
なにするgem?
例えば...
class SomeExternalClass
def method_you_know(*args)
...
end
end
↑みたいな(外部のライブラリなど、直接触りづらい)クラ
スがあったとして
なにするgem?
例えば...
Predef.predef SomeExternalClass, :method_you_know do|*args|
p args
super(*args)
end
↑みたいにすると
対象のメソッドの前後に好きな処理を加えられちゃう♪
この場合、引数を出力する処理を加えちゃう♪
なにするgem?
やってることは実質これ↓と同じ
module Wrapper
def method_you_know *args
p args
super(*args)
end
end
class SomeExternalClass
prepend Wrapper
end
詳しくはprependでググってください。
なにするgem?
余計なmoduleを定義しなくて済む
ただそれだけなんで別に無理に使う必要もない
事例
アプリ上で発行されうる全てのSQLと、その場所を把握した
い
ActiveRecord任せのためどこでどんなクエリを発行するか
分かりにくくなりがち
ただし、SELECT・DELETE・UPDATEのみ。
INSERTやその他DDLなどはテストでだけ実行されるケース
が多い。
あと、要件上あまり関心がなかった。
事例
アプリ上で発行されうる全てのSQLと、その場所を把握した
い
Mysql2::Client#queryメソッドをラップした上で、全テスト
を実行
最終的にActiveRecordが実行するはずなので、漏れがない
ラップしたqueryメソッドで受け取った引数と、バックトレース
をログに出す
カバレッジもとり、カバーできてない分のみコードを読む
事例
アプリ上で発行されうる全てのSQLと、その場所を把握した
い
こんな感じ...
Predef.predef Mysql2::Client, :query do|sql|
if sql =~ /SELECT|UPDATE|DELETE/
puts sql
pp caller
end
super(sql) # 引数を忘れずに
end
事例
アプリ上で発行されうる全てのSQLと、その場所を把握した
い
で、こんな感じの出力が!
SELECT * from your_apps_table WHERE ...
["/path/to/your_app/app/models/foo.rb:355:in `some_method_in_model'",
...]
Tips
Refinementsも用意してます
使い方
using Predef::Refinements
Mysql2::Client.predef :query do|sql|
...
end
まとめ(みなさん向け)
$ gem install predef
まとめ(みなさん向け)
require 'predef'
using Predef::Refinements
Mysql2::Client.predef :query do|sql|
puts sql if sql =~ /.../
super(sql)
end
まとめ(私向け)
さっさと bundle exec rake release しなさい。
こちらも終了: predef

More Related Content

Predefを使ったsqlのトレース