#new_record?函数用于判断记录是否已保存,但在after_save
钩子中,它总是返回false。有没有办法确定记录是新创建的还是从更新修改的旧记录?
我希望不使用另一个回调函数,如before_create
在模型中设置标志或要求对数据库进行另一个查询。
任何建议都将不胜感激。
编辑:需要在after_save
钩子中确定,并且对于我的特定用例,没有updated_at
或updated_on
时间戳。
#new_record?函数用于判断记录是否已保存,但在after_save
钩子中,它总是返回false。有没有办法确定记录是新创建的还是从更新修改的旧记录?
我希望不使用另一个回调函数,如before_create
在模型中设置标志或要求对数据库进行另一个查询。
任何建议都将不胜感激。
编辑:需要在after_save
钩子中确定,并且对于我的特定用例,没有updated_at
或updated_on
时间戳。
我想在after_save
回调中使用这个。
一个更简单的解决方案是使用id_changed?
(因为它不会在update
上改变),甚至可以使用created_at_changed?
如果存在时间戳列。
更新:正如@mitsy指出的那样,如果需要在回调之外进行此检查,则使用id_previously_changed?
。请参见文档。
after_save
之外,这两个领域都无法正常工作。 - fatuhokuid_changed?
will be false after the record is saved (outside of the hooks at least). In that case, you can use id_previously_changed?
- mltsyid_changed?
被弃用了,推荐使用 saved_change_to_id?
。在使用 id_changed?
后,我在控制台上看到了以下消息:“DEPRECATION WARNING: The behavior of attribute_changed?
inside of after callbacks will be changing in the next version of Rails. The new return value will reflect the behavior of calling the method after save
returned (e.g. the opposite of what it returns now). To maintain the current behavior, use saved_change_to_attribute?
instead.” - theblang在我所知道的情况下,这里没有Rails的魔法,您需要自己完成。您可以使用虚拟属性来清理代码...
在您的模型类中:
def before_save
@was_a_new_record = new_record?
return true
end
def after_save
if @was_a_new_record
...
end
end
对于那些拥有updated_at
时间戳的人,还有另一种选择:
if created_at == updated_at
# it's a newly created record
end
after_save
回调中,除了第一次创建时,是否可能在任何其他时间使created_at
等于updated_at
?” - colllinafter_save
回调中,created_at
和updated_at
将相等。在其他所有情况下,在after_save
回调中它们不会相等。 - bschaeffer有一个after_create
回调函数,只在记录是新记录时,在记录保存后才会被调用。如果这是一个已经存在并发生更改和保存的记录,则可以使用after_update
回调函数。无论是after_create
还是after_update
被调用后,都会调用after_save
回调函数。
如果需要在新记录保存后执行一次操作,请使用after_create
。
更多信息请参见:http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
after_create
会在关联被创建之前被调用,因此,如果您需要确保所有内容都已创建,则需要使用after_save
。 - Niels Kristianafter_create
时,记录还没有被存储到数据库中。 - svelandiag由于对象已经保存,因此您需要查看之前的更改。ID仅在创建后更改。
# true if this is a new record
@object.previous_changes[:id].any?
还有一个实例变量@new_record_before_save
。您可以通过以下方式访问它:
# true if this is a new record
@object.instance_variable_get(:@new_record_before_save)
这两种方式都不太好看,但它们可以让你知道对象是否是新创建的。希望有所帮助!
after_save
回调中,但是这两个都无法识别这条新记录。 - MCB@object.previous_changes[:id].any?
非常简单而优雅。在记录更新后它对我很有效(我没有从after_save
中调用它)。 - thekingoftruth@object.id_previously_changed?
稍微好看了一点。 - aNobleafter_save
中,您需要查看 changes[:id]
而不是 previous_changes[:id]
。然而,在 Rails 5.1 中将发生更改(请参见 https://github.com/rails/rails/pull/25337 中的讨论)。 - gmcnaughtonprevious_changes.key?(:id)
。 - Sebastián PalmaRails 5.1+ 的方式:
user = User.new
user.save!
user.saved_change_to_attribute?(:id) # => true
有一个方法叫做previously_new_record?
,正好可以用于这种情况。
user = User.new
user.new_record? # => true
user.previously_new_record? # => false
user.save
user.new_record? # => false
user.previously_new_record? # => true
看起来调用saved_change_to_id?
的提议解决方法不再起作用了。我使用的是Rails 7。
after_save
内创建对象时,changes
和previous_changes
方法的结果是空哈希{}
。因此,像id_changed?
这样的attribute_changed?
方法将无法按预期工作。changes
中 - 检查changes
是否为空。一旦确认为空,您必须正在创建对象:after_save do
if changes.empty?
# code appropriate for object creation goes here ...
end
end