如何确定after_save中的记录是刚刚创建还是更新

发布于 2024-10-17 05:04:13 字数 304 浏览 3 评论 0原文

#new_record?函数确定记录是否已保存。但在 after_save 挂钩中它始终为 false。有没有办法判断该记录是新创建的记录还是更新后的旧记录?

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

任何建议表示赞赏。

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

The #new_record? function determines if a record has been saved. But it is always false in the after_save hook. Is there a way to determine whether the record is a newly created record or an old one from update?

I'm hoping not to use another callback such as before_create to set a flag in the model or require another query into the db.

Any advice is appreciated.

Edit: Need to determine it in after_save hook, and for my particular use case, there is no updated_at or updated_on timestamp

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

迷雾森÷林ヴ 2024-10-24 05:04:13

我希望将其用于 after_save 回调。

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

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

I was looking to use this for an after_save callback.

A simpler solution is to use id_changed? (since it won't change on update) or even created_at_changed? if timestamp columns are present.

Update: As @mitsy points out, if this check is needed outside of callbacks then use id_previously_changed?. See docs.

娇女薄笑 2024-10-24 05:04:13

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

在您的模型类中:

def before_save
  @was_a_new_record = new_record?
  return true
end

def after_save
  if @was_a_new_record
    ...
  end
end

No rails magic here that I know of, you'll have to do it yourself. You could clean this up using a virtual attribute...

In your model class:

def before_save
  @was_a_new_record = new_record?
  return true
end

def after_save
  if @was_a_new_record
    ...
  end
end
违心° 2024-10-24 05:04:13

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

if created_at == updated_at
  # it's a newly created record
end

Yet another option, for those who do have an updated_at timestamp:

if created_at == updated_at
  # it's a newly created record
end
压抑⊿情绪 2024-10-24 05:04:13

有一个 after_create 回调,仅当记录是新记录时才会调用,在保存后。如果这是已更改并保存的现有记录,则还可以使用 after_update 回调。在调用 after_createafter_update 后,这两种情况都会调用 after_save 回调。

如果您需要在保存新记录后执行某些操作,请使用 after_create

更多信息请参见:http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

There is an after_create callback which is only called if the record is a new record, after it is saved. There is also an after_update callback for use if this was an existing record which was changed and saved. The after_save callback is called in both cases, after either after_create or after_update is called.

Use after_create if you need something to happen once after a new record has been saved.

More info here: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

全部不再 2024-10-24 05:04:13

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

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

Since the object has already been saved, you would you need to look at the previous changes. The ID should only change after a create.

# true if this is a new record
@object.previous_changes[:id].any?

There is also an instance variable @new_record_before_save. You can access that by doing the following:

# true if this is a new record
@object.instance_variable_get(:@new_record_before_save)

Both are pretty ugly, but they would allow you to know whether the object has been newly created. Hope that helps!

美人骨 2024-10-24 05:04:13

有一个名为 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 上。

There is a method called previously_new_record? for exactly this use case.

user = User.new

user.new_record? # => true
user.previously_new_record? # => false

user.save

user.new_record? # => false
user.previously_new_record? # => true

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

Looks like the proposed workaround by calling saved_change_to_id? doesn't work anymore. I'm on Rails 7.

千秋岁 2024-10-24 05:04:13

Rails 5.1+ 方式:

user = User.new
user.save!
user.saved_change_to_attribute?(:id) # => true

Rails 5.1+ way:

user = User.new
user.save!
user.saved_change_to_attribute?(:id) # => true
心如狂蝶 2024-10-24 05:04:13

对于 Rails 4(在 4.2.11.1 上检查),changesprevious_changes 方法的结果是 after_save 内创建对象时的空哈希值 {}。因此,像 id_changed? 这样的 attribute_changed? 方法将无法按预期工作。

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

after_save do
  if changes.empty?
    # code appropriate for object creation goes here ...
  end
end

For Rails 4 (checked on 4.2.11.1) results of changes and previous_changes methods are empty hashes {} on object creation inside after_save. So attribute_changed? methods like id_changed? won't work as expected.

But you can take advantage of this knowledge and - knowing that at least 1 attribute has to be in changes on update - check if changes is empty. Once you confirm that it's empty, you must be during object creation:

after_save do
  if changes.empty?
    # code appropriate for object creation goes here ...
  end
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文