Ruby:如何使自定义DSL接受变量

时间:2014-02-05 09:27:45

标签: ruby-on-rails ruby ruby-on-rails-3

我有这堂课:

class Items
    def initialize &block
      (block.arity < 1 ?  (instance_eval &block) : block.call(self)) if block_given?
    end

    def button_id button_id=nil
      unless @button_id.present?
        raise "button_id must be supplied" if button_id.nil?
        @button_id = button_id
      end
      @button_id
    end
end

现在,当我这样做时,它有效:

Items.new do
   button_id 1
end

但是当我这样做时,它会失败,因为我认为它不在同一范围内:

@button = Button.find(params[:button_id]
Items.new do
   button_id @button.id
end

如何解决这个问题以使范围外的参数?

谢谢!

3 个答案:

答案 0 :(得分:0)

试试这个:

class Items
  def self.dsl
    new.tap do |item|
      yield item
    end
  end

  def button_id(button_id)
    @button_id = button_id
  end
end

@button = Button.find(params[:button_id])

item = Items.dsl do |item|
  item.button_id(@button.id)
end

puts item.inspect

答案 1 :(得分:0)

原来我需要做的就是将参数传递给块,如下所示:

Items.new do |item|
   item.button_id @button.id
end

不太漂亮的DSL但有效。

答案 2 :(得分:0)

我不认为这是DSL的正确用例,只需通过参数分配属性即可。

class Item
  attr_accessor: :button_id

  def initialize(args)
    button_id = args[:button_id]
  end
end

另一个问题在于您的使用方法。如果不将其分配给变量

,则该实例没什么价值
item = Item.new button_id: button_id