Ruby on rails 我有相同的getter/setter代码用于多个虚拟属性-我可以用eval重构吗?

Ruby on rails 我有相同的getter/setter代码用于多个虚拟属性-我可以用eval重构吗?,ruby-on-rails,attributes,model,refactoring,virtual-attribute,Ruby On Rails,Attributes,Model,Refactoring,Virtual Attribute,我已经为虚拟属性编写了定制的getter和setter方法,用于将小数转换为整数以存储在数据库中。这是从数据库中的真实属性(年费)获取/设置的三个虚拟属性(年费)之一: def annual_fee_dollars @annual_fee_dollars || int_to_dec(annual_fee) end def annual_fee_dollars=(string) @annual_fee_dollars = string self.annual_fee = dec_to

我已经为虚拟属性编写了定制的getter和setter方法,用于将小数转换为整数以存储在数据库中。这是从数据库中的真实属性(年费)获取/设置的三个虚拟属性(年费)之一:

def annual_fee_dollars
  @annual_fee_dollars || int_to_dec(annual_fee)
end

def annual_fee_dollars=(string)
  @annual_fee_dollars = string
  self.annual_fee = dec_to_int(string)
end
与其将所有这些代码重复三次,不如像这样重构代码/安全吗/是“Rails方式”吗:

def self.decimal_get_and_set(variable, suffix)
  eval (
    "def #{variable + suffix}
      @#{variable + suffix} || int_to_dec(self.#{variable})
    end
    def #{variable+suffix}=(string)
      @#{variable+suffix} = string
      self.#{variable} = dec_to_int(string)
    end")
end
self.decimal_get_and_set "annual_fee", "_dollars"
self.decimal_get_and_set "interest_purchase", "_percent"
self.decimal_get_and_set "interest_cash", "_percent"
或者有没有更干净的方法来构建这种功能

如果这是一个“主观问题”,请道歉。在某种程度上,所有重构问题都有一定的主观性,但我认为这个问题仍然有一定的主观性。很高兴在这个问题上得到纠正


干杯

我认为您的方法很好,但我不建议使用
eval
,主要是因为已经有了一种更合适的ruby元编程方法。阅读有关对象和方法的文档

看起来像你想要的,你不需要自己使用
eval
。我可能会提出如下建议,但你是对的——所有重构问题本质上都有点主观。祝你好运

{'annual_fee' => '_dollars', 'interest_purchase' => '_percent', 'interest_cash' => '_percent'}.each_pair do |variable, suffix|
  # Define getters
  define_method "#{variable+suffix}" do
    instance_variable_get("@#{variable+suffix}") || int_to_dec(send("#{variable}")
  end

  # Define setters
  define_method "#{variable+suffix}=" do
    ...
  end
end

为什么不让一个方法在给定属性名的情况下获取和设置一个值,为这两个别名方法定义两个getter和setter来curry定义的方法呢。我会这样做,而不是eval,因为我发现eval代码会让东西更混乱,这取决于你如何使用它。您显示的代码Brett决不是超级复杂,但为了可读性,我觉得这是一个棘手的问题。谢谢您的回答。这似乎比“eval”解决方案更干净、更容易阅读。我不知道您使用的各种类/模块方法(instance\u variable\u get等)。我仍然试图将两个“define_methods”封装在一个class方法中,然后调用它三次(每个属性一次),而不是设置“each_pair”do循环。我无法解释原因,除非将来编辑时会更清楚。谢谢你的回答@德米特里-我没听说过咖喱法。经过研究,我不确定我是否有Ruby smarts来很好地实现它。另外,我正在运行1.8.7-看起来curry直到1.9.0才被引入?getter方法有点错误-它要么获取实例变量,要么(如果是nil)获取实例变量的int_to_dec。我已经更正了它,使用send方法获取底层属性