如何更新after_save中的属性而不会导致rails 2.3中的递归?

pet*_*est 14 ruby-on-rails callback save ruby-on-rails-2

我有一个模型,附有Paperclip的视频.保存后,我使用保存的视频生成缩略图.我需要在每次保存后执行此操作,即使尚未上传新视频,因为用户可以更改捕获缩略图的时间.

我目前正在使用after_post_process来执行此操作,但它只会在上传文件时生成缩略图(这是回调,它是Paperclip的一部分).

理想情况下我会使用这样的after_save回调:

after_save :save_thumbnail
def save_thumbnail
  #generate thumbnail...
  self.update_attributes(
    :thumbnail_file_name => File.basename(thumb), 
    :thumbnail_content_type => 'image/jpeg'
  )
end
Run Code Online (Sandbox Code Playgroud)

不幸的是,update_attributes调用save,然后调用before_save回调导致无限循环.是否有一种简单的方法来规避这种行为?

zak*_*ssi 10

回调中的任何update_attribute一个after_save都会在Rails3 +中引起递归.应该做的是:

after_save :updater!
# Awesome Ruby code
# ...
# ...

private

  def updater!
    self.update_column(:column_name, new_value) # This will skip validation gracefully.
  end
Run Code Online (Sandbox Code Playgroud)


Dyl*_*kow 9

您可以将其包装在条件中,例如:

def save_thumbnail
  if File.basename(thumb) != thumbnail_file_name
    self.update_attributes(
      :thumbnail_file_name => File.basename(thumb), 
      :thumbnail_content_type => 'image/jpeg'
    )
  end
end
Run Code Online (Sandbox Code Playgroud)

这样它只会运行一次.


the*_*gah 8

Rails 2:

Model.send(:create_without_callbacks)
Model.send(:update_without_callbacks)
Run Code Online (Sandbox Code Playgroud)

Rails 3:

Vote.skip_callback(:save, :after, :add_points_to_user)
Run Code Online (Sandbox Code Playgroud)

看到这个问题:

如何跳过ActiveRecord回调?

  • 如果还有其他需要运行的回调怎么办? (2认同)