2012-07-01 40 views
0
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>> 

如何訪問嵌套方法?訪問DSL時的嵌套方法

puts warcraft.battle_net # => iccup 
puts warcraft.side #=> #<Proc:[email protected]: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) 

回答

1

puts warcraft.game因爲你Warcraft#game方法需要一個塊,你像一個屬性訪問器調用,它拋出一個錯誤。

我不確定你在這裏需要什麼,但如果你想用Warcraft#game方法來獲得當前的遊戲以及建立一個新的遊戲,那麼你可以返回當前的遊戲,如果沒有給出一個塊,像這樣:

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