#new_record? function确定是否已保存记录。但是after_save
钩子总是假的。有没有办法确定记录是新创建的记录还是更新的旧记录?
我希望不使用其他回调(如before_create
)在模型中设置标记或要求对数据库进行另一次查询。
任何建议表示赞赏。
修改:需要在after_save
挂钩中确定它,对于我的特定用例,没有updated_at
或updated_on
时间戳
答案 0 :(得分:152)
我希望将其用于after_save
回调。
更简单的解决方案是使用id_changed?
(因为它不会在update
上更改),如果存在时间戳列,则使用created_at_changed?
。
更新:正如@mitsy指出的那样,如果在回调之外需要进行此检查,则使用id_previously_changed?
。见docs。
答案 1 :(得分:30)
我知道这里没有铁杆魔法,你必须自己做。你可以使用虚拟属性来清理它......
在您的模型类中:
def before_save
@was_a_new_record = new_record?
return true
end
def after_save
if @was_a_new_record
...
end
end
答案 2 :(得分:24)
对于那些做的人有updated_at
时间戳的另一种选择:
if created_at == updated_at
# it's a newly created record
end
答案 3 :(得分:23)
只有当记录是新记录时才会调用after_create
回调,保存后会调用。如果这是一个已更改并保存的现有记录,还可以使用after_update
回调。在调用after_save
或after_create
之后,在两种情况下都会调用after_update
回调。
如果您在保存新记录后需要执行某些操作,请使用after_create
。
此处有更多信息:http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
答案 4 :(得分:16)
由于对象已经保存,您需要查看以前的更改。该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)
两者都非常丑陋,但它们可以让你知道对象是否是新创建的。希望有所帮助!
答案 5 :(得分:5)
采用5.1+轨道:
user = User.new
user.save!
user.saved_change_to_attribute?(:id) # => true
答案 6 :(得分:1)
对于Rails 4(在4.2.11.1中进行了检查),changes
和previous_changes
方法的结果是{}
内部对象创建时的空哈希值after_save
。因此,attribute_changed?
之类的id_changed?
方法无法按预期工作。
但是您可以利用这些知识,并且-知道在更新时changes
中至少必须有一个属性-检查changes
是否为空。一旦确认为空,就必须在对象创建过程中:
after_save do
if changes.empty?
# code appropriate for object creation goes here ...
end
end
答案 7 :(得分:-1)
即使我知道:id
正常情况下也不会改变,但我还是想具体一点,但
(byebug) id_change.first.nil?
true
确定特定的东西总是便宜,而不是发现非常奇怪的意外错误。
如果我希望从不可信的参数中获取true
标志,则采用相同的方式
def foo?(flag)
flag == true
end
这样可以节省大量时间,避免出现奇怪的错误。