メタプログラミングRuby読みメモ 5

6章 コードを記述するコード

Kernel#eval

  • Kernel#evalは、ブロックではなくRubyのコードの文字列を受け取る
  • これをコード文字列と呼ぶ
  • eval は渡されたコード文字列を実行する
  • instance_evalとclass_evalもブロックだけでなく、コード文字列も受け取れる

Bindingオブジェクト

  • Binding はスコープをまとめたもの
  • Binding を使ってローカルスコープを取得すればそのスコープを持ち回すことができる
  • Kernel#bindingメソッドで生成できる
  • スコープを持っているため、evalでBindingオブジェクトに渡すことでそのスコープでコードを評価できる
    • すごい!こんな仕組みだったんだ
  • pryというgemにはオブジェクトのスコープでインタラクティブセッションを開くObject#pryメソッドが定義されている
  • これを用いてbindingのpryを呼び出すことでデバッガのように使うことができる

irb

  • irbは標準入力やファイルをパースして、それぞれの行をevalに渡すプログラム
  • こうしたプログラムはコードプロセッサと呼ばれる

eval の問題点

  • コード文字列はシンタックスハイライトが効かない
  • 外部からのコード文字列を受け取るとコードインジェクションの危険がある

オブジェクトの汚染とセーフレベル

  • 潜在的に安全ではないオブジェクトに自動的に汚染の印がつく
    • 汚染オブジェクトには、ウェブフォーム、ファイル、コマンドライン、システム変数、プログラムが読み込んだ文字列などが含まれる
  • 汚染された文字列を操作して新しい文字列を作ると、その新しい文字列も汚染される
  • taind?メソッドで確認できる
  • Ruby はセーフレベルを設定できる
  • セーフレベルが0より大きいと汚染した文字列を評価できない

フックメソッド

  • イベントをキャッチできるメソッド
  • Class#inheritedは継承されたときに実行してくれるメソッド
    • デフォルトでは何もしないのでオーバーライドして使う
  • Module#includedModule#prependedでモジュールのライフサイクルにプラグインできる
  • Module#extendedでモジュールを拡張したときに入り込める
  • 特異メソッドをキャッチするときにはKernel#singleton_method_addedなどを使う