0

需要知道如何重构代码:

attr_accessor :product
attr_reader :name, :mark

def name=(value)
  super unless product.present?
end

def mark=(value)
  super unless product.present?
end

... and a whole bunch of method of sorts.

这个想法很简单 - 如果已经设置了产品,则拒绝分配值。但是上面的代码根本不是 DRY。

有任何想法吗?

4

2 回答 2

2
attr_accessor :product
attr_reader :name, :mark

["name", "mark"].each do |method|
 define_method("#{method}=") do |value|
  super(value) unless product.present?
 end
end
于 2013-10-22T22:08:12.913 回答
1

您可以创建一个方法attr_*来处理这个问题。这是通过重新打开Class类并定义以下方法来完成的。

def attr_validator(*args)

  #We simply iterate through each passed in argument...
  args.each do |arg|

    # Create an attr_reader
    self.class_eval("
      def #{arg};
        @#{arg};
      end
    ")

    # Here we hardcode "product" since this every attribute
    # checks itself against this object
    self.class_eval("
      def #{arg}=(val);
        super unless product.present?;
      end
    ")                      

  end
end

通过这种方式,我们摆脱了将属性附加到预处理器方法(在我的例子中attr_validator)的冗余,以及用于元编程目的的不同数组。

可以这样使用...

attr_accessor :product
attr_validator :name, :mark, :price, :stock # ...and so on
于 2013-10-22T22:41:20.937 回答