在ActiveRecord中如何在before_save回调中使用'changed'(dirty)?

时间:2009-09-30 11:48:08

标签: ruby-on-rails activerecord

我想将我的摘要字段设置为正文字段的清理版本,但前提是用户不提供自己的摘要,即。 params [:document] [:summary]是空白的。

如果我创建一个新记录,如果我输入一个保存的摘要,如果我不使用该主体来生成摘要,这似乎工作正常。

但是,当我更新记录时,摘要总是被覆盖。从我的日志文件中我可以看到'generate_summary'被调用两次,第二次'changes'hash为空。

class Document << ActiveRecord::Base
  # Callbacks
  before_save  :generate_summary

private

  def generate_summary
    @counter ||= 1

    logger.debug '$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'
    logger.debug @counter.to_s
    logger.debug 'changes: ' + self.changes.inspect
    self.summary = Sanitize.clean(self.body).to(255) if self.body && (!self.summary_changed? or self.summary.blank?)
    @counter = @counter + 1
end

登录更新:

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

1

更改:{“summary”=&gt; [“asdasdasdasd”,“three.co.uk”]}

页面更新(0.7毫秒)更新documents设置meta_description ='three.co.uk',summary ='three.co.uk',updated_at = '2009-09-30 11:37:08'在哪里id = 77

SQL(0.6ms)COMMIT

SQL(0.1ms)BEGIN

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

2

更改:{}

页面更新(0.5ms)更新documents设置meta_description ='asdasdasdasd',summary ='asdasdasdasd',updated_at ='2009-09-30 11: 37:08'在哪里id = 77

4 个答案:

答案 0 :(得分:3)

你的控制器可能会保存两倍,如@nasmorn所说。在更新摘要之前,您还可以检查您的身体是否已更改。

if self.body_changed? && (!self.summary_changed? or self.summary.blank?)
  self.summary = Sanitize.clean(self.body).to(255)
end

答案 1 :(得分:1)

唯一合乎逻辑的解释是控制器以某种方式保存了两次。 这个日志来自您在记录上调用update的控制台,还是来自通过控制器发出的实际请求?

答案 2 :(得分:1)

似乎'update_attributes'触发了before_save回调,因此在我的控制器中'generate_summary''update_attributes'调用两次,'save'调用一次。这不是预期的行为。

按照@vincent的建议检查正文已经改变,似乎可以防止意外行为。

答案 3 :(得分:-1)

我绕过多个before_save调用的方式是引入

attr_accessor :object_saved

他们在回调方法中

before_save :before_save_method

我这样做

def before_save_method
  if self.object_saved.nil?
     self.object_saved = true
    # Do Something 
  end
end