Advanced Rails--Ruby基本技術(8)--メタプログラミングテクニック3


Bindings
BindingsはRubyコード計算のコンテキスト環境を提供する.1つのbindingは、コードの特定の位置に存在する変数と方法のセットです.Rubyコードのどの文もbindingとして計算できます.このbindingはKernel#binddingで取得できます.BindingはBindingクラスのオブジェクトで、他のオブジェクトと同じように渡すことができます.

	class C
	  binding # => #<Binding:0x2533c>
	  def a_method
	    binding
	  end
	end
	binding # => #<Binding:0x252b0>
	C.new.a_method # => #<Binding:0x25238>

Railsの足場発生器はbindingを用いる良い例を提供した.

	class ScaffoldingSandbox
	  include ActionView::Helpers::ActiveRecordHelper
	  attr_accessor :form_action, :singular_name, :suffix, :model_instance

	  def sandbox_binding
	    binding
	  end

	  # ...
	end

ScaffoldingSandboxは、テンプレートをレンダリングするためのクリーンな環境です.ERbはbindingのコンテキストでテンプレートをレンダリングできるので、ERbのテンプレートに利用可能なAPIを作成しました.

	part_binding = template_options[:sandbox].call.sandbox_binding
	# ...
	ERB.new(File.readlines(part_path).join,nil,'-').result(part_binding)

前述したコードブロックは閉パッケージです.閉じたbindingは、アクセスする変数とメソッドの集合として彼の状態として表現されます.Proc#bindingで閉パッケージのbindingを得ることができます.

	def var_from_binding(&b)
	  eval("var", b.binding)
	end
	
	var = 123
	var_from_binding {} # => 123
	var = 456
	var_from_binding {} # => 456

ここでは、bindingに使用する方法としてProcを使用しました.コードブロックのbinding(コンテキスト)にアクセスすることで、binding上で簡単なevalでローカル変数にアクセスできます.