👀

Rails ライブラリのデバッグ方法(Monkey Patch)

2024/11/15に公開

Railsアプリケーションで特定の処理やメソッドについて詳細なデバッグ情報が必要な場合、Monkey Patch(モンキーパッチ)を活用して、ライブラリやメソッドの挙動をカスタマイズする方法があります

モンキーパッチの基礎知識

モンキーパッチとは、既存のクラスやメソッドを再定義または拡張するテクニックです
これにより、元々のコードを上書きする形で、独自の処理を追加したり、動作を変更したりできます
今回は、モンキーパッチを使ってライブラリの内部処理にログを挟む方法を紹介します

特定のライブラリの挙動を確認する

  1. バックトレースなどで、対象のライブラリやメソッドの場所を確認
    デバッグ対象の処理でエラーが発生する場合は、そのバックトレースを確認し、どのファイルに記載されているかを特定します
    エラーが発生しない場合は、任意の箇所でraiseを挟んで強制的にエラーを発生させることで、バックトレースを取得します
  2. 該当箇所のソースコードを確認する
    Gemfile.lockなどから該当のライブラリのバージョンを特定します
    バージョンが判明したら、GitHubなどでそのバージョンに合ったライブラリのソースコードを参照します
    これにより、実装内容を確認しながらMonkey Patchの適用箇所を明確にします
  3. モンキーパッチを適用して動作確認
    モンキーパッチの内容を作成し、デバッグ用のログを挿入します

モンキーパッチの適用

モンキーパッチ用のディレクトリ構成

Railsでは、lib/monkey_patches ディレクトリにモンキーパッチ用のファイルを格納し、
それらを初期化時に読み込むようにするのが一般的です

ディレクトリ構成イメージ
/app
/config/initializers/__monkey_patches.rb
/lib/monkey_patches/**/*

初期設定ファイル

config/initializers に初期化ファイルを作成

初期設定ファイル(config/initializers/__monkey_patches.rb)
Dir.glob(Rails.root.join('lib/monkey_patches/**/*.rb')).sort.each do |f|
  require f
end

モンキーパッチの内容

例えば、Hogeというクラスのfuga?メソッドに対してモンキーパッチを適用し、デバッグ用のログを追加する例です

hoge.rb
class Hoge
  def fuga?(args)
    a = piyo(args[:a]) # 引数aを変換するメソッド
    b = piyo(args[:b]) # 引数bを変換するメソッド
    a == b
  end
end
パッチ用のファイル内容(lib/monkey_patches/hoge_patch.rb)
module HogePatch
  def fuga?(args)
    a = piyo(args[:a])
    b = piyo(args[:b])
    Rails.logger.debug "Debug - piyo a: #{a}" # 引数aの変換結果をログ出力
    Rails.logger.debug "Debug - piyo b: #{b}" # 引数bの変換結果をログ出力
    a == b
  end
end

Hoge.prepend(HogePatch)

全体の流れ

  1. ファイル名をconfig/initializers/__monkey_patches.rbにしていることで、他のinitializerよりも優先して実行される
    ※プロダクトの設定状況によって異なる可能性があります
  2. initializerによりlib/monkey_patches 配下にある全てのrbファイルがアプリケーションの起動時に読み込まれる
  3. moduleをprependしているため、元のクラスに対して前置メソッドとしてパッチのメソッドが追加される
  4. ブラウザやRails consoleなどで実際に処理を実行すると、パッチのメソッドが呼び出されてログが記録される

モンキーパッチの注意事項

モンキーパッチは非常に強力なテクニックであり、今回はその一例として、特定メソッドの呼び出しタイミングでの変数の状態確認を紹介しました
また、モンキーパッチはデバッグ以外にも、ライブラリのバージョンアップが難しい場合や、Gem本体への修正が困難なプロジェクトでの運用目的としても利用されます

既存のコードに対する直接的な影響が大きく、
モンキーパッチをデバッグ目的以外で利用される場合には以下の点に注意してください

  • 本番環境にはなるべく適用しない
    パフォーマンスや予期しないエラーのリスクがあるため、開発環境やテスト環境でのみ使用するのが望ましいです
  • ライブラリのバージョンに注意する
    ライブラリのバージョン更新によって内部コードが変更されると、モンキーパッチが意図通りに動作しなくなることがあります
    そのため、ライブラリのバージョンが異なると適用されない場合や、予期しない挙動を示す可能性があることを考慮してください
  • 既存のモンキーパッチに注意
    プロジェクト内に他のモンキーパッチが適用されている場合、GitHubなどで確認したコードと異なる挙動をする可能性があります
    また、ライブラリのバージョンアップ時にモンキーパッチの適用範囲が影響を受けていないか確認が必要です
    Gemバージョンをコードで比較するにしておき、バージョンアップ時に検知できるようにしておくと安心です

よきデバッグライフを

Discussion