我有一个模型,附有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
不幸的是,update_attributes调用save,然后调用before_save回调导致无限循环。是否有一种简单的方法来规避这种行为?
您可以将其包装在条件中,例如:
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
这样它只会运行一次。
在qailsxswpoi回调中的任何update_attribute
将导致Rails3 +中的递归。应该做的是:
after_save
以下是一些关于它的文档:after_save :updater!
# Awesome Ruby code
# ...
# ...
private
def updater!
self.update_column(:column_name, new_value) # This will skip validation gracefully.
end
Rails 2:
https://guides.rubyonrails.org/active_record_callbacks.html#skipping-callbacks
Rails 3:
Model.send(:create_without_callbacks)
Model.send(:update_without_callbacks)
看到这个问题:
Vote.skip_callback(:save, :after, :add_points_to_user)
您可以(并且应该)检查您是否确实需要更新缩略图:
How to skip ActiveRecord callbacks?
在这里,您可以阅读更多关于'脏'属性:after_save :save_thumbnail
def save_thumbnail
if capture_time_changed? #assuming capture_time contains time when the thumbnail has to be captured
#generate thumbnail...
self.update_attributes(
:thumbnail_file_name => File.basename(thumb),
:thumbnail_content_type => 'image/jpeg'
)
end
end
虽然我不确定它是否仍然可以看到after_save中的属性更改。您可以使用成员变量来指示更改,以防万一。
您可以将其作为http://apidock.com/rails/ActiveRecord/Dirty运行。
验证后,更新缩略图,然后继续保存,但只需使用分配方法
before_save
因为那不会调用save,所以你不会递归,但是在方法退出后会立即保存。
这样的东西应该有用,除非你有明确的理由在保存后需要它。
由于您不是更新单独的对象,而是更新同一个对象,因此这也将为您节省数据库调用。这就是我如何做时间戳和类似的事情。