109

#new_record?函数确定是否已保存记录。但这始终是错误的after_save。有没有办法确定记录是新创建的记录还是更新的旧记录?

我希望不要使用另一个回调,例如before_create在模型中设置标志或要求对数据库进行另一个查询。

任何建议表示赞赏。

编辑:需要在after_save钩子中确定它,对于我的特定用例,没有updated_atupdated_on时间戳

4

8 回答 8

188

我正在寻找将其用于after_save回调。

一个更简单的解决方案是使用id_changed?(因为它不会在 上更改update)或者即使created_at_changed?存在时间戳列。

更新:正如@mitsy 指出的那样,如果在回调之外需要此检查,则使用id_previously_changed?. 请参阅文档

于 2011-08-25T00:41:06.383 回答
32

我知道这里没有轨道魔法,你必须自己做。您可以使用虚拟属性来清理它...

在您的模型类中:

def before_save
  @was_a_new_record = new_record?
  return true
end

def after_save
  if @was_a_new_record
    ...
  end
end
于 2011-02-12T00:58:24.150 回答
30

对于那些确实updated_at时间戳的人来说,还有另一种选择:

if created_at == updated_at
  # it's a newly created record
end
于 2013-02-05T00:28:32.247 回答
23

有一个after_create回调,只有在记录是新记录时才会调用,在它被保存之后after_update如果这是已更改并保存的现有记录,则还有一个回调供使用。after_save回调在这两种情况下都会被调用,或者在或者after_createafter_update调用之后。

after_create如果您需要在保存新记录后发生某事,请使用此选项。

更多信息在这里:http ://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

于 2012-11-28T21:25:05.007 回答
18

由于对象已经保存,您需要查看以前的更改。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)

两者都很丑陋,但它们可以让您知道对象是否是新创建的。希望有帮助!

于 2013-09-15T17:36:57.233 回答
11

Rails 5.1+方式:

user = User.new
user.save!
user.saved_change_to_attribute?(:id) # => true
于 2020-03-30T15:14:57.320 回答
1

对于 Rails 4(在 4.2.11.1 上检查)changesprevious_changes方法的结果是{}内部对象创建的空哈希after_save。所以attribute_changed?像这样的方法id_changed?不会按预期工作。

但是您可以利用这些知识 - 知道至少 1 个属性必须在changes更新时 - 检查是否changes为空。一旦你确认它是空的,你必须在对象创建期间:

after_save do
  if changes.empty?
    # code appropriate for object creation goes here ...
  end
end
于 2020-06-13T16:47:47.960 回答
1

有一种方法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

来源:https ://api.rubyonrails.org/v6.1.4/classes/ActiveRecord/Persistence.html#method-i-previously_new_record-3F

看起来通过调用提出的解决方法saved_change_to_id?不再起作用。我在 Rails 7 上。

于 2022-01-05T07:27:45.977 回答