Buscar..


Sintaxis

  • eval "fuente"
  • eval "fuente", vinculante
  • eval "fuente", proc
  • binding.eval "source" # igual a eval "source", binding

Parámetros

Parámetro Detalles
"source" Cualquier código fuente de Ruby
binding Una instancia de clase Binding
proc Una instancia de la clase Proc

Evaluación de instancias

El método instance_eval está disponible en todos los objetos. Evalúa el código en el contexto del receptor:

object = Object.new

object.instance_eval do
  @variable = :value
end

object.instance_variable_get :@variable  # => :value

instance_eval establece self para object durante la duración del bloque de código:

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

El receptor también se pasa al bloque como su único argumento:

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

El método instance_exec difiere a este respecto: en su lugar, pasa sus argumentos al bloque.

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

Evaluando una cadena

Cualquier String puede ser evaluada en tiempo de ejecución.

class Example
  def self.foo
    :foo
  end
end

eval "Example.foo" #=> :foo

Evaluando dentro de un enlace

Ruby realiza un seguimiento de las variables locales y de la self variable a través de un objeto llamado enlace. Podemos obtener un enlace de un ámbito con Kernel#binding y evaluar una cadena dentro de un enlace a través de 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

Creación dinámica de métodos a partir de cadenas

Ruby ofrece define_method como un método privado en módulos y clases para definir nuevos métodos de instancia. Sin embargo, el 'cuerpo' del método debe ser un Proc u otro método existente.

Una forma de crear un método a partir de datos de cadena sin procesar es utilizar eval para crear un Proc a partir del código:

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
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow