Recherche…


Syntaxe

  • eval "source"
  • eval "source", liaison
  • eval "source", proc
  • binding.eval "source" # égal à eval "source", binding

Paramètres

Paramètre Détails
"source" Tout code source Ruby
binding Une instance de classe Binding
proc Une instance de classe Proc

Évaluation d'instance

La méthode instance_eval est disponible sur tous les objets. Il évalue le code dans le contexte du récepteur:

object = Object.new

object.instance_eval do
  @variable = :value
end

object.instance_variable_get :@variable  # => :value

instance_eval définit lui- self object pour la durée du bloc de code:

object.instance_eval { self == object }  # => true

Le récepteur est également transmis au bloc comme seul argument:

object.instance_eval { |argument| argument == object }  # => true

La méthode instance_exec diffère à cet égard: elle transmet ses arguments au bloc à la place.

object.instance_exec :@variable do |name|
  instance_variable_get name  # => :value
end

Evaluer une chaîne

Toute String peut être évaluée au moment de l'exécution.

class Example
  def self.foo
    :foo
  end
end

eval "Example.foo" #=> :foo

Evaluer à l'intérieur d'une liaison

Ruby conserve la trace des variables locales et self variables self via un objet appelé binding. Nous pouvons obtenir une liaison avec une portée en appelant la Kernel#binding et évaluer la chaîne à l'intérieur d'une liaison 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

Création dynamique de méthodes à partir de chaînes

Ruby propose define_method comme méthode privée sur les modules et les classes pour la définition de nouvelles méthodes d'instance. Cependant, le «corps» de la méthode doit être un Proc ou une autre méthode existante.

Une façon de créer une méthode à partir de données de chaîne brutes consiste à utiliser eval pour créer un Proc à partir du code:

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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow