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