为什么 after_create_commit 的存在使我的 after_update_commit 永远不会触发?

发布于 2025-01-10 01:01:37 字数 414 浏览 0 评论 0原文

我看到这样的场景:

class User
  def thing; puts "hello"; end
  after_update_commit :thing
  after_create_commit :thing
end

在执行 user.update first_name: rand 时,after_update_commit 永远不会触发 但如果我注释掉 after_create_commit,它确实有效。

  • 最后宣布的一方获胜。
  • 似乎仅适用于 _commit 回调,
  • 仅发生在同一方法的多个回调中

这是 Rails 错误还是有原因?

导轨 6.1.4.6

I'm seeing a scenario where i have something like this:

class User
  def thing; puts "hello"; end
  after_update_commit :thing
  after_create_commit :thing
end

the after_update_commit never fires when doing user.update first_name: rand
but if i comment out after_create_commit, it does work.

  • Whichever one is declared last is the one that wins.
  • seems to only be for _commit callbacks
  • only happens with multiple callbacks for same method

Is this a Rails bug or is there a reason for this?

rails 6.1.4.6

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

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

发布评论

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

评论(2

还给你自由 2025-01-17 01:01:37

https://guides.rubyonrails.org/active_record_callbacks.html#transaction-callbacks

使用具有相同方法名称的 after_create_commit 和 after_update_commit 只会允许定义的最后一个回调生效,因为它们都在内部别名为 after_commit,后者会覆盖之前定义的具有相同方法名称的回调。

如果没有条件,则解决方案:

after_commit :thing, on: [:update, :create]

如果有条件,则解决方案(在本例中,更新时为 is_active?

after_commit :thing, on: [:update, :create]

def thing
  # id_previously_changed? is only true when record is created
  unless id_previously_changed?
    return unless is_active?
  end

# ...
end

https://guides.rubyonrails.org/active_record_callbacks.html#transaction-callbacks

Using both after_create_commit and after_update_commit with the same method name will only allow the last callback defined to take effect, as they both internally alias to after_commit which overrides previously defined callbacks with the same method name.

solution if don't have conditions:

after_commit :thing, on: [:update, :create]

solution if do have condition (in this case, is_active? on update)

after_commit :thing, on: [:update, :create]

def thing
  # id_previously_changed? is only true when record is created
  unless id_previously_changed?
    return unless is_active?
  end

# ...
end
你不是我要的菜∠ 2025-01-17 01:01:37

正如 John Bachir 回答中所说,您可能对创建和更新操作有不同的条件(这些条件可能很复杂)。我最终得到的结论是:

class User
  def thing; puts "hello"; end
  after_commit :thing_on_create, on: :create, if: :create_condition?
  after_commit :thing_on_update, on: :update, if: :update_condition?

  alias_method :thing_on_create, :thing
  alias_method :thing_on_update, :thing

  def create_condition?
    Time.now.monday?
  end

  def update_condition?
    active?
  end
end

在我看来,它更具可读性(并且不会影响方法本身)。

As it was said in John Bachir answer you may have different conditions for create and for update actions (and these conditions may be complicated). I ended up with:

class User
  def thing; puts "hello"; end
  after_commit :thing_on_create, on: :create, if: :create_condition?
  after_commit :thing_on_update, on: :update, if: :update_condition?

  alias_method :thing_on_create, :thing
  alias_method :thing_on_update, :thing

  def create_condition?
    Time.now.monday?
  end

  def update_condition?
    active?
  end
end

It is a little bit more readable (and does not affect the method itself) IMO.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文