Ruby Language
動的評価
サーチ…
構文
- eval "source"
- eval "source"、バインディング
- eval "source"、proc
- binding.eval「ソース」に等しい#
eval "source", binding
パラメーター
インスタンス評価
instance_eval
メソッドは、すべてのオブジェクトで使用できます。レシーバのコンテキストでコードを評価します。
object = Object.new
object.instance_eval do
@variable = :value
end
object.instance_variable_get :@variable # => :value
instance_eval
は、コードブロックの持続時間中、 self
からobject
設定しobject
。
object.instance_eval { self == object } # => true
レシーバは、唯一の引数としてブロックに渡されます。
object.instance_eval { |argument| argument == object } # => true
この点でinstance_exec
メソッドは異なりinstance_exec
。代わりに、引数をブロックに渡します。
object.instance_exec :@variable do |name|
instance_variable_get name # => :value
end
文字列の評価
実行時に任意のString
を評価できます。
class Example
def self.foo
:foo
end
end
eval "Example.foo" #=> :foo
バインディング内の評価
Rubyは、バインディングと呼ばれるオブジェクトを介してローカル変数とself
変数を追跡します。 Kernel#binding
を呼び出してスコープのバインディングを取得し、バインディング内の文字列をBinding#eval
経由で評価することができます。
b = proc do
local_variable = :local
binding
end.call
b.eval "local_variable" #=> :local
def fake_class_eval klass, source = nil, &block
class_binding = klass.send :eval, "binding"
if block
class_binding.local_variable_set :_fake_class_eval_block, block
class_binding.eval "_fake_class_eval_block.call"
else
class_binding.eval source
end
end
class Example
end
fake_class_eval Example, <<-BLOCK
def self.foo
:foo
end
BLOCK
fake_class_eval Example do
def bar
:bar
end
end
Example.foo #=> :foo
Example.new.bar #=> :bar
文字列からメソッドを動的に作成する
Rubyはdefine_method
を、新しいインスタンスメソッドを定義するためのモジュールとクラスのプライベートメソッドとして提供しています。しかし、メソッドの '本体'は、 Proc
または別の既存のメソッドでなければなりません。
生の文字列データからメソッドを作成する1つの方法は、 eval
を使用してコードからProcを作成することです。
xml = <<ENDXML
<methods>
<method name="go">puts "I'm going!"</method>
<method name="stop">7*6</method>
</methods>
ENDXML
class Foo
def self.add_method(name,code)
body = eval( "Proc.new{ #{code} }" )
define_method(name,body)
end
end
require 'nokogiri' # gem install nokogiri
doc = Nokogiri.XML(xml)
doc.xpath('//method').each do |meth|
Foo.add_method( meth['name'], meth.text )
end
f = Foo.new
p Foo.instance_methods(false) #=> [:go, :stop]
p f.public_methods(false) #=> [:go, :stop]
f.go #=> "I'm going!"
p f.stop #=> 42
Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow