Ruby Language
Dynamische Bewertung
Suche…
Syntax
- eval "Quelle"
- eval "source", verbindlich
- eval "source", proc
- binding.eval "source" # gleich
eval "source", binding
Parameter
Parameter | Einzelheiten |
---|---|
"source" | Beliebiger Ruby-Quellcode |
binding | Eine Instanz der Binding Klasse |
proc | Eine Instanz der Proc Klasse |
Instanzbewertung
Die Methode instance_eval
ist für alle Objekte verfügbar. Es wertet Code im Kontext des Empfängers aus:
object = Object.new
object.instance_eval do
@variable = :value
end
object.instance_variable_get :@variable # => :value
instance_eval
setzt self
für die Dauer des Codeblocks auf object
:
object.instance_eval { self == object } # => true
Der Empfänger wird auch als einziges Argument an den Block übergeben:
object.instance_eval { |argument| argument == object } # => true
Die instance_exec
Methode unterscheidet sich in dieser Hinsicht: Sie übergibt stattdessen ihre Argumente an den Block.
object.instance_exec :@variable do |name|
instance_variable_get name # => :value
end
Einen String auswerten
Jeder String
kann zur Laufzeit ausgewertet werden.
class Example
def self.foo
:foo
end
end
eval "Example.foo" #=> :foo
Auswerten innerhalb einer Bindung
Ruby verfolgt die Spuren von lokalen Variablen und self
Variable über ein Objekt namens Bindung. Wir können die Bindung eines Bereichs mit der aufrufenden Kernel#binding
und die Zeichenfolge innerhalb einer Bindung über Binding#eval
auswerten.
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
Methoden dynamisch aus Strings erstellen
Ruby bietet define_method
als private Methode für Module und Klassen zur Definition neuer Instanzmethoden. Der 'Rumpf' der Methode muss jedoch eine Proc
oder eine andere vorhandene Methode sein.
Eine Methode zum Erstellen einer Methode aus Roh-String-Daten besteht darin, eval
zum Erstellen eines Proc aus dem Code zu verwenden:
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