2
[:initial_amount, :rate_increase_amount].each do |method|
  define_method method do
    self["#{method}_in_cents".to_sym].to_f/100 if self["#{method}_in_cents".to_sym]
  end

  define_method "#{method}=" do |_value|
    self["#{method}_in_cents".to_sym] = _value.to_f * 100
  end
end

它给出了以下错误:

NoMethodError: undefined method `initial_amount_in_cents' for #<ViolationType:0x6220a88>

我试图将其重写为:

def initial_amount_in_cents
  initial_amount_in_cents.to_f/100 if initial_amount_in_cents
end

def rate_increase_amount_in_cents
  rate_increase_amount_in_cents.to_f/100 if rate_increase_amount_in_cents
end

def initial_amount= (value)
  initial_amount_in_cents = value.to_f * 100
end

def rate_increase_amount= (value)
  rate_increase_amount_in_cents = value.to_f * 100
end

但它给了我这个错误:

ERROR SystemStackError: stack level too deep
4

1 回答 1

2

问题

你有几个,包括:

  1. 过于“聪明”的代码。不要没有充分的理由做这样的事情。
  2. 递归调用。您可能会考虑使用定义?或避免这种情况的东西。
  3. 一个缺少很多上下文的例子。

DRY 并不意味着晦涩难懂。如果代码的编写方式对您没有意义,请重构它以使其清晰。

它可能试图做什么

该代码显然试图为_in_cents接受浮点数的相关方法动态定义一个方法。你必须问作者为什么他(或她)这样写,但这就是它的目的,不管它目前是否适合你。

可能的解决方案

尽管如此,这可能会有所帮助。假设您已经在模型中定义了属性,initial_amount那么rate_increase_amount您应该能够简化对Module#define_method的调用。例如:

class YourRailsModel
  %i[initial_amount rate_increase_amount].each do |method|
    # You don't have a real Rails model here, so we create accessors to simulate
    # model attributes.
    attr_accessor method

    define_method "#{method}_in_cents" do
      Integer(Float send(method) * 100)
    end
  end
end

model = YourRailsModel.new
model.initial_amount = 0.97
# => 0.97

model.initial_amount_in_cents
# => 97
于 2013-05-23T20:33:41.433 回答