Rails中模型属性的延迟设置?

时间:2009-04-16 19:59:01

标签: ruby-on-rails model

我有一个通过解析数据文件生成的模型。有几个有趣的值在原始数据文件中不存在,但可以从那些值中获得。

但是,许多这些派生值的计算成本很高,所以我想在计算完成后将它们存储在数据库中。

我试过这个:

def profit
  if not self[:profit]
    update_attribute :profit, expensive_computation
  end
  self[:profit]
end

不幸的是,这只能完成一半的工作。计算出的值会被存储,但每次我调用profit时,它都会再次计算该值。

更新:

事实证明问题不在方法中,但在之前的一个find_by_sql语句中,Rails对模型的id感到困惑。我最终得到的代码是:

def profit
  unless read_attribute(:profit)
    update_attribute(:profit, expensive_computation ) 
    self.save!
  end
  read_attribute(:profit)
end

4 个答案:

答案 0 :(得分:2)

您创建一个新方法并从中删除读取逻辑。也许是这样的

 def update_profit
    update_attribute :profit, expensive_computation
 end

这样你就可以分开阅读逻辑,只需使用方法来获得rails给你的profit

 @model.profit

其中@model是属性profit所在的任何类的实例。

答案 1 :(得分:0)

代码应该去哪里取决于何时可以计算利润(例如,一旦记录首次被保存,或者有时会更晚?),以及利润是否可以改变。< / p>

一般情况下,最好将计算放在某种before_create / before_save调用中,只有在可以计算和/或更改时才会保存它

vrish88是正确的,您应该单独保留profit方法,除非您确实需要在需要时随时计算此数据。如果那真的是你需要的,试试:

def profit
  update_attribute(:profit, expensive_computation) unless read_attribute(:profit)

  read_attribute(:profit)
end

答案 2 :(得分:0)

这对我来说很好。我的第一个想法是:你在if not self[:profit]行中有拼写错误吗?

答案 3 :(得分:0)

def profit
  super || update_attribute(:profit, expensive_computation)
  return super
end

如果利润列中包含信息,只需调用对象的原始利润方法,该方法将从数据库中返回profit列的内容。

否则,(即profit列的值为nil)使用update_attribute方法计算profit值并将其存储到数据库中,然后简单地再次从数据库返回值。

如果您已经在数据库中,或者只是profit,如果昂贵的计算已经运行,那么您希望获得true的值,只需这样做(update_attribute返回true或false) :

def profit
  super || update_attribute(:profit, expensive_computation)
end