如何更新 after_save 中的属性而不导致 Rails 2.3 中的递归?
我有一个模型,其中附有 Paperclip 的视频。保存后,我使用保存的视频生成缩略图。我需要在每次保存后执行此操作,即使尚未上传新视频,因为用户可以更改捕获缩略图的时间。
我目前正在使用 after_post_process 来执行此操作,但它只会在上传文件时生成缩略图(这是回形针的一部分的回调)。
理想情况下,我会使用像这样的 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 回调导致无限循环。有没有一种简单的方法来规避这种行为?
I've got a model which has a video attached with Paperclip. After it saves I use the saved video to generate a thumbnail. I need to do this after every save, even when a new video hasn't been uploaded, because the user can change the time where the thumbnail is captured.
I am currently using after_post_process to do this, but it will only generate the thumbnail when uploading a file (this is a callback which is part of Paperclip).
I would ideally use an after_save callback like this:
after_save :save_thumbnail
def save_thumbnail
#generate thumbnail...
self.update_attributes(
:thumbnail_file_name => File.basename(thumb),
:thumbnail_content_type => 'image/jpeg'
)
end
Unfortunately update_attributes calls save, which then calls the before_save callback causing an infinite loop. Is there a simple way to circumvent this behaviour?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在 Rails3+ 中,
after_save
回调中的任何update_attribute
都会导致递归。应该做的是:
这里有一些关于它的文档: https://guides.rubyonrails .org/active_record_callbacks.html#skipping-callbacks
Any
update_attribute
in anafter_save
callback will cause recursion, in Rails3+.What should be done is:
Here is some documentation about it: https://guides.rubyonrails.org/active_record_callbacks.html#skipping-callbacks
您可以将其包装在条件中,例如:
这样它只会运行一次。
You could wrap it in a conditional, something like:
That way it would only run once.
Rails 2:
Rails 3:
请参阅此问题:
如何跳过 ActiveRecord 回调?
Rails 2:
Rails 3:
See this question:
How to skip ActiveRecord callbacks?
您可以(并且应该)检查是否确实需要更新缩略图:
在这里您可以阅读有关“脏”属性的更多信息:http://apidock.com/rails/ActiveRecord/Dirty
虽然我不确定它是否仍然可以看到after_save中的属性变化。您可以使用成员变量来指示更改,以防万一它不能。
You can(and should) check if you actually need to update the thumbnail:
Here you can read more about 'dirty' attributes: http://apidock.com/rails/ActiveRecord/Dirty
Although I'm not sure if it still can see the attribute changes in after_save. You can use a member variable to indicate changes in case it can't.
您可以将其作为
before_save
运行。验证通过后,更新缩略图,然后让它继续保存,但只需使用赋值方法即可,
因为不会调用save,所以不会递归,但方法退出后会立即保存。
类似的东西应该可以工作,除非有明确的原因您在保存后需要它。
由于您不是更新单独的对象,而是更新同一个对象,因此这也将为您节省一次数据库调用。这也是我做时间戳和类似事情的方式。
You can run it as a
before_save
instead.After it has been validated, update the thumbnail, then let it go on to be saved, but just use the assignment methods
Since that won't call save, you wont recurse, but it will immediately be saved after the method exits.
Something like that should work, unless there is an explicit reason you need it in after save.
Since you are not updating a separate object, but the same one, this will save you a database call as well. This is How i do timestamps and things like that too.