Szukaj…


Składnia

  • eval „źródło”
  • eval „source”, wiążące
  • eval „source”, proc
  • bind.eval „source” # równe eval "source", binding

Parametry

Parametr Detale
"source" Dowolny kod źródłowy Ruby
binding Instancja klasy Binding
proc Instancja klasy Proc

Ocena wystąpienia

Metoda instance_eval jest dostępna na wszystkich obiektach. Ocenia kod w kontekście odbiornika:

object = Object.new

object.instance_eval do
  @variable = :value
end

object.instance_variable_get :@variable  # => :value

instance_eval ustawia self na object na czas trwania bloku kodu:

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

Odbiornik jest również przekazywany do bloku jako jedyny argument:

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

Metoda instance_exec różni się pod tym względem: zamiast tego przekazuje argumenty do bloku.

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

Ocena ciągu

Każdy String może być oceniany w czasie wykonywania.

class Example
  def self.foo
    :foo
  end
end

eval "Example.foo" #=> :foo

Ocena wewnątrz wiązania

Ruby śledzi zmienne lokalne i zmienne self za pośrednictwem obiektu zwanego powiązaniem. Możemy uzyskać powiązanie zakresu z wywołaniem Kernel#binding i ocenić ciąg znaków wewnątrz powiązania za pomocą 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

Dynamiczne tworzenie metod z ciągów

Ruby oferuje define_method jako prywatną metodę modułów i klas do definiowania nowych metod instancji. Jednak „treść” metody musi być Proc lub inną istniejącą metodą.

Jednym ze sposobów utworzenia metody na podstawie nieprzetworzonych danych jest użycie eval do utworzenia Proc z kodu:

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow