Ruby Language
Ocena dynamiczna
Szukaj…
Składnia
- eval „źródło”
- eval „source”, wiążące
- eval „source”, proc
- bind.eval „source” # równe
eval "source", binding
Parametry
Parametr | Detale |
---|---|
"source" | Dowolny kod źródłowy Ruby |
binding | Instancja klasy Binding |
proc | Instancja klasy Proc |
Ocena wystąpienia
Metoda instance_eval
jest dostępna na wszystkich obiektach. Ocenia kod w kontekście odbiornika:
object = Object.new
object.instance_eval do
@variable = :value
end
object.instance_variable_get :@variable # => :value
instance_eval
ustawia self
na object
na czas trwania bloku kodu:
object.instance_eval { self == object } # => true
Odbiornik jest również przekazywany do bloku jako jedyny argument:
object.instance_eval { |argument| argument == object } # => true
Metoda instance_exec
różni się pod tym względem: zamiast tego przekazuje argumenty do bloku.
object.instance_exec :@variable do |name|
instance_variable_get name # => :value
end
Ocena ciągu
Każdy String
może być oceniany w czasie wykonywania.
class Example
def self.foo
:foo
end
end
eval "Example.foo" #=> :foo
Ocena wewnątrz wiązania
Ruby śledzi zmienne lokalne i zmienne self
za pośrednictwem obiektu zwanego powiązaniem. Możemy uzyskać powiązanie zakresu z wywołaniem Kernel#binding
i ocenić ciąg znaków wewnątrz powiązania za pomocą 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
Dynamiczne tworzenie metod z ciągów
Ruby oferuje define_method
jako prywatną metodę modułów i klas do definiowania nowych metod instancji. Jednak „treść” metody musi być Proc
lub inną istniejącą metodą.
Jednym ze sposobów utworzenia metody na podstawie nieprzetworzonych danych jest użycie eval
do utworzenia Proc z kodu:
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