-
Notifications
You must be signed in to change notification settings - Fork 21.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
after_commit :my_callback, :on => :create fires on update too #14493
Comments
@basvk could you check with 4.0.4? |
Checked with Rails 4.0.4: I can confirm this happens in 4.0.4 as well. I also realized that I'm actually updating the record inside the after_commit callback... (setting a status when the after_commit task was successful). |
Could you create a gist reproducing the issue. You can found a template in the contributing guide. |
Sure, here: https://gist.github.com/basvk/9807527 |
@laurocaetano The issue apparently is caused by doing an update (at the db level) of the record inside the after_commit callback. In your gist, you are not saving the updated attribute inside the after_commit, and the issue does not get triggered. Actually the updated attribute does not get persisted until the post.save line, so in real life the change to the attribute would actually be lost. So as it is currently, it is not possible to update the record in an after_commit callback without getting into an infinite loop, despite the :on => :create... |
BTW here is a real life example: "After committing the new record to the db, a report file should be automatically created, and the url to the newly created report should be saved in that changed record." |
#8937 sure looks related from the description, but I have no way to confirm for sure. I guess it is all connected to each other anyway. I can only confirm that the issue described in this ticket did not occur in 4.0.0.beta1, I had it in production for a couple of months without problems. |
The revert indeed fixes the issue for me, thanks. |
I think there is no easy way to make this work 😿 Correct me if I'm wrong, but when the The easy way to have this working, could be something like this: class User
after_commit :do_after_commit, on: :create
def do_after_commit
name = 'New name'
end
end
user = User.create! # triggers the `after_commit` callback.
user.save # does the update here. |
+1 |
@laurocaetano When you use the Of course, if you omit the So what you are proposing already exists (and functioned correctly until 4.0.0), but instead of |
@basvk a So @laurocaetano is correct, there is no way to make this work. |
ok, so that's the flaw: |
I'd love to see some sort of solution to make this work. In the past I've done things like this to simulate the desired behaviour: after_create :flag_that_this_is_a_create
after_commit :some_action_i_care_about
def flag_that_this_is_a_create
@this_is_a_create = true
end
def some_action_i_care_about
if @this_is_a_create
some_side_effects
end
end Kind of ugly, and it feels like a hack. |
@basvk this is still true, the commit was already done, the create action still not since it only ends when the last callback end. @jherdman unfortunately to make this work we have to change the callback lifecycle to put I'm closing this issue now. |
@basvk I'm sorry, it was a typo 😅
It only run once at creation, the problem is the
@jherdman it will work the way I described, you don't need to use a variable to control the lifecycle. |
This is typical for Rails and makes dealing with it very painful. Mind you I'm using rails since 2005.
This functionality was working fine in earlier versions, I use it extensively in several projects. It breaks on a point release (it's always on a point release) and instead of it being fixed (well the revert fixed it, but I assume it won't stay that way for long), the ticket gets closed, which means that I will have to fix several projects, probably without being able to bill my clients for it, or stay with the previous version forever. Sorry for the rant, and it's of course not a such a big deal, but it does feel like death by a 1000 paper cuts. I'm not using Rails anymore for new projects due to the pain with upgrades and the pain with deployments and setup. The high maintenance is killing. |
The revert changed the behavior back to the same behavior it had in Rails 3.2 so if something was broken is 4.0.0.beta1 (as you can see it is a beta release). We still can fix it, but no promises. |
Thanks for reopening, I appreciate your open mind in this. |
You are welcome, I should not have closed it. Sorry about that. |
Was this issue ever resolved? I'm on |
This is still an issue as of rails 4.2.2. I can't say anything about newer releases, but I would imagine they still suffer from this as well. |
Ran reproduction script above, and Rails master is currently passing. Working on a bisect (and hopefully a solution) for 4-2-stable right now. |
Ok, so it looks like this bug is not existent on master. Reproduction script I used can be found here. Another slight complication -- it appears as though this behavior has been in the 4.x.x series for a while, because |
We don't move forward. If it is fixed only on master that is fine. |
+1: Isn't it very common for someone to want to call |
@woniesong92 Why not use |
@dimoon You mean that:
This will work for most of the cases, but what about saving dependent models created in callback? |
The script from #14493 (comment) passes on master, but only because it no longer reproduces the bug. #18367 is a proposed fix which does make the script pass, even using There's some confusion in the thread, so to clarify: this bug is present in every stable release of Rails since at least 3.2. It was fixed in 4.0.0.beta1, but the fix was reverted before 4.0.0.rc1. |
So maybe we should open this issue again? |
No, we shouldn't #14493 (comment) |
@rafaelfranca But then I would suggest to remove the |
It works for the use case it exists. It only don't work when you do a update action inside a callback that is running because an create action started. In this case Rails consider all actions create. |
I encounter this infinite loop issue when using Currently I use |
I did the following hack and It works with me: after_commit :do_after_commit, on: :create
def do_after_commit
self.class.find(id).update(name: 'New name')
reload
end |
I just want to point out this is still an issue with rails 5. zakwanhaj's work around works for me but this really should be fixed as it can be quite dangerous for those that find the bug the hard way. |
and using update_columns to skip callbacks isn't a proper solution. a lot of users depend on those call backs for things like auditing |
For rails version <= 4.1 use This solve my problem. |
@syedmahmad the syntax for how to limit to |
calling anything in |
I'm stumbling again and again over this issue every year, it's really a big pain and it's sad that this doesn't get fixed - this is clearly a bug in my opinion. Having this issue now with latest Rails 5 version. |
The problem seems to boil down to the object not being loaded properly in
I would expect the above However, if I remove |
I keep being bitten by this again and again. Each time I eventually reach this thread and I remember WHY this happens, but unfortunately the counterintuitive nature of the after_commit :on => :create is problematic to say the least. |
Having the same problem with Rails 5.2.0 too. It looks like this, and everything works fine.
|
After upgrading from 4.0.0.beta1 to 4.1.0.rc2 my after_commit hooks are now getting triggered on update too, despite the :on => :create option.
The text was updated successfully, but these errors were encountered: