Acceso a métodos anidados cuando DSL

class Warcraft 

  def initialize &block
    instance_eval &block
  end

  def method_missing name, *args, &block
    instance_variable_set("@#{name}".to_sym, args[0])
    self.class.send(:define_method, name, proc { instance_variable_get("@#{name}")})
  end

  def game &block
    @game = Game.new &block
  end

  class Game 
    def initialize &block
      instance_eval &block
    end

    def method_missing name, *args, &block
      instance_variable_set("@#{name}".to_sym, args[0])
      self.class.send(:define_method, name, proc { instance_variable_get("@#{name}")})
    end   
  end

end

warcraft = Warcraft.new do
  name "Warcraft III"
  battle_net :iccup

  game do
    side :sentinels
    hero "Furion"
    rune_appear_every 2
  end
end

puts warcraft.inspect # => #<Warcraft:0x00000000be3e80 @name="Warcraft III", @battle_net=:iccup, @game=#<Warcraft::Game:0x000000009c6c38 @side=:sentinels, @hero="Furion", @rune_appear_every=2>>

¿Cómo acceder a métodos anidados?

puts warcraft.battle_net # => iccup
puts warcraft.side #=> #<Proc:0x000000010de6d8@dsl.rb:9 (lambda)>
puts warcraft.game #=> dsl.rb:18:in `instance_eval': block not supplied (ArgumentError)
puts warcraft.game.side #=> dsl.rb:18:in `instance_eval': block not supplied (ArgumentError)

preguntado el 01 de julio de 12 a las 02:07

1 Respuestas

puts warcraft.game arroja un error porque su Warcraft#game El método requiere un bloque y lo está llamando como un atributo de acceso.

No estoy seguro exactamente de lo que necesita aquí, pero si desea utilizar el Warcraft#game método para obtener el juego actual y configurar un nuevo juego, entonces podría devolver el juego actual si no se proporciona un bloque, algo como esto:

def game &block
  if block_given?
    @game = Game.new &block
  else
    @game
  end
end

Respondido 01 Jul 12, 10:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.