Ruby Language
Dynamische evaluatie
Zoeken…
Syntaxis
- eval "bron"
- eval "bron", bindend
- eval "source", proc
- binding.eval "source" # gelijk aan
eval "source", binding
parameters
Parameter | Details |
---|---|
"source" | Elke Ruby-broncode |
binding | Een exemplaar van Binding class |
proc | Een exemplaar van Proc klasse |
Exemplaarevaluatie
De methode instance_eval
is beschikbaar op alle objecten. Het evalueert code in de context van de ontvanger:
object = Object.new
object.instance_eval do
@variable = :value
end
object.instance_variable_get :@variable # => :value
instance_eval
stelt self
om object
te object
voor de duur van het codeblok:
object.instance_eval { self == object } # => true
De ontvanger wordt ook doorgegeven aan het blok als het enige argument:
object.instance_eval { |argument| argument == object } # => true
De methode instance_exec
verschilt in dit opzicht: in plaats daarvan worden de argumenten doorgegeven aan het blok.
object.instance_exec :@variable do |name|
instance_variable_get name # => :value
end
Een string evalueren
Elke String
kan tijdens runtime worden geëvalueerd.
class Example
def self.foo
:foo
end
end
eval "Example.foo" #=> :foo
Evalueren in een binding
Robijn houdt lokale variabelen en self
variabel via een object genoemd binding. We kunnen binding van een scope krijgen door Kernel#binding
aan te roepen en string binnen een binding te evalueren via 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
Dynamisch methoden maken van tekenreeksen
Ruby biedt define_method
als een define_method
voor modules en klassen voor het definiëren van nieuwe instantiemethoden. De 'body' van de methode moet echter een Proc
of een andere bestaande methode zijn.
Een manier om een methode te maken op basis van onbewerkte tekenreeksgegevens is door eval
te gebruiken om een Proc van de code te maken:
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