Skip to content
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

Fix counter cache behaviour on rails 4.2 #192

Merged
merged 10 commits into from
Mar 18, 2015

Conversation

sergey-alekseev
Copy link
Contributor

Gist

The PR adds Rails 4.2 compatibility and particularly addresses counter cache changes in rails/rails#14735 and rails/rails#14765.

Details

The introduced test test_counter_cache_column_update_on_destroy with counter cache update on #destroy would break with Rails 4.2. The reason is Rails 4.2 changes introduced in this commit Make counter cache decrementation on destroy idempotent. Try and compare:

# On the commit 'Make counter cache decrementation on destroy idempotent'
# test_counter_cache_column_update_on_destroy fails
gem 'rails', github: 'rails', ref: '655a3667aa99ae3f7e68024b3971b5783d6396bf'

Another introduced test test_counter_cache_column_update_on_really_destroy with counter cache update on #really_destroy! would break with Rails 4.1. It starts to succeed with the commit mentioned above. Try and compare with the commit done right before the Make counter cache decrementation on destroy idempotent:

# Right before the commit 'Make counter cache decrementation on destroy idempotent'
# test_counter_cache_column_update_on_really_destroy fails
gem 'rails', github: 'rails', ref: 'dd063f6ef436b5e6a594e70eeb50532a09ef7a57'

Notes

Apart of the fix I felt free to refactor the code a bit, remove 3 annoying deprecation warnings and add 1 deprecation warning (helpful for future compatibility).

Not sure whether #restore should increment counter cache back. In my current application I need it to be the same behaviour as it's now – don't increment counter cache after restore. So I leave it as is. Let me know if you need this behaviour, I'd include the commit to this or separate PR. The test for #restore is simple:

assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
related_model.restore
assert_equal 1, parent_model_with_counter_cache_column.reload.related_models_count

Another proposal: probably it would be good to bump a minor version with Rails 4.2 support. I've noticed you didn't bumb it for Rails 4.1.

BTW love the gem! ❤️ It does a good job.

@sergey-alekseev sergey-alekseev changed the title Switch to rails 4 2 Switch to rails 4.2 Dec 14, 2014
@sergey-alekseev
Copy link
Contributor Author

Pushed the fix for test_counter_cache_column_update_on_destroy.

This is a workaround actually. Since ActiveRecord::CounterCache.each_counter_cached_associations is private. We shouldn’t use it. Proposals for the proper fix are welcome.

The reason the previous version stopped working is affected_rows returns 0 at active_record/counter_cache.rb#L142. If you follow the method call you’ll find that it’s called at active_record/persistence.rb#L486. Probably we’d better override the return value in ActiveRecord::Relation.delete_all at active_record/relation.rb#L481.

@sergey-alekseev
Copy link
Contributor Author

I've made test_counter_cache_column_update_on_really_destroy to succeed.

This is another workaround actually. My goal is Rails 4.2 support and it works well with Rails 4.2. I’m
leaving this bug not fixed for Rails 4.1 for the time being. We should fix it later though. Proposals for the proper fix are welcome.

@sergey-alekseev sergey-alekseev force-pushed the switch-to-rails-4-2 branch 2 times, most recently from c51cf6e to df67172 Compare December 14, 2014 19:37
@pomartel
Copy link

👍 I just tested it with one of my app and the fix works for me. I would also vote to fix incrementing the counter cache on a record restore.

@sergey-alekseev
Copy link
Contributor Author

Thanks @pomartel for testing.
Just a note that if you want to use this fix until it's merged you can add this line to your Gemfile: gem 'paranoia', github: 'sergey-alekseev/paranoia', branch: 'switch-to-rails-4-2'.

@jhawthorn
Copy link
Collaborator

@sergey-alekseev Thanks very much for this work. I've merged all the deprecation fixes, but I need more time to review before merging the counter cache fixes.

I want to avoid anyone experiencing different behaviour when switching from rails 4.1 to 4.2. The conditional test cases suggest that is probably the case here.

@sergey-alekseev
Copy link
Contributor Author

@jhawthorn let me know if you need my help. Good to see some changes were merged, even after more than a month.

@thibaudgg
Copy link

👍

@thibaudgg
Copy link

@sergey-alekseev could you rebase your PR on master please, for some reason paranoia_destroyed? is not defined in your fork. Thanks!

http://edgeguides.rubyonrails.org/4_2_release_notes.html#active-record-d
eprecations
> Deprecated passing Active Record objects to .find or .exists?. Call
id on the objects first.
Commits in Rails:
rails/rails@d92ae6c
0bd270
rails/rails@d35f003
9596f7
rails/rails@c0609dd
356b35
This is a workaround actually. Since
`ActiveRecord::CounterCache.each_counter_cached_associations` is
private. We shouldn’t use it. Proposals for the proper fix are welcome.

The reason the previous version stopped working is `affected_rows`
returns `0` at
[active_record/counter_cache.rb#L142](https://github.com/rails/rails/blo
b/ef99d4cd3ecc58a8c1484740b2fb5447dbda23ab/activerecord/lib/active_recor
d/counter_cache.rb#L142). If you follow the method call you’ll find
that it’s called at
[active_record/persistence.rb#L486](https://github.com/rails/rails/blob/
ef99d4cd3ecc58a8c1484740b2fb5447dbda23ab/activerecord/lib/active_record/
persistence.rb#L486). Probably we’d better override the return value in
`ActiveRecord::Relation.delete_all` at
[active_record/relation.rb#L481](https://github.com/rails/rails/blob/ef9
9d4cd3ecc58a8c1484740b2fb5447dbda23ab/activerecord/lib/active_record/rel
ation.rb#L481).
My goal is Rails 4.2 support and it works well with Rails 4.2. I’m
leaving this bug not fixed for Rails 4.1 for the time being.
This will allow to detect counter cached columns changes in callbacks
like `after_destroy` or `after_commit on: :destroy`.
@sergey-alekseev
Copy link
Contributor Author

@thibaudgg rebased. paranoia_destroyed? was not defined because my PR was created 2 months ago. paranoia_destroyed? has been committed later 2b0db84.

You may want to fix the last commented test. Authors seems doesn't have interest merging this PR. And the old not rebased branch addresses my needs pretty well. No need to upgrade for me.

@thibaudgg
Copy link

Hey @radar, what's the status on that PR?
It would be great to have paranoia working fine with Rails 4.2 and counter_cache feature, do you plan to fix it directly on master?

Thanks for your work on this gem, much appreciated!

@thibaudgg
Copy link

@sergey-alekseev thanks for the rebase!

@radar
Copy link
Collaborator

radar commented Feb 17, 2015

Which PR?

On 17 Feb 2015, at 23:42, Thibaud Guillaume-Gentil notifications@github.com wrote:

Hey @radar, what's the status on that PR?
It would be great to have paranoia working fine with Rails 4.2 and counter_cache feature, do you plan to fix it directly on master?

Thanks for your work on this gem, much appreciated!


Reply to this email directly or view it on GitHub.

@sergey-alekseev
Copy link
Contributor Author

@radar this one I suppose.

@thibaudgg
Copy link

Yep, this one: #192!

assert_equal 1, parent_model_with_counter_cache_column.reload.related_models_count
related_model.destroy
assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
# related_model.restore
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work? Why is it commented out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I asked about restore in the Notes of the PR's description. Personally I don't need such a behaviour. So removing in sergey-alekseev@d252fab.

related_model.destroy

assert related_model.instance_variable_get(:@after_destroy_callback_called)
# assert related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it commented out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I wrote here:

You may want to fix the last commented test.

I don't know why it stopped working with the new changes introduced during last 2 months. Your help would be appreciated.

@jhawthorn jhawthorn changed the title Switch to rails 4.2 Fix counter cache behaviour on rails 4.2 Feb 18, 2015
I asked about `restore` in the
[Notes](rubysherpas#192 (comment)) of
the PR's description. Personally I don't need such a behaviour. So
removing.
This has been removed and should no longer exist.
rubysherpas#192 (comment)
@sergey-alekseev
Copy link
Contributor Author

@thibaudgg np

@ghost
Copy link

ghost commented Feb 23, 2015

When can we expect this merged?

@radar
Copy link
Collaborator

radar commented Feb 23, 2015

When can I expect people to be patient and to realise we have lives outside of open source?

On 24 Feb 2015, at 02:36, Anthony Collini notifications@github.com wrote:

When can we expect this merged?


Reply to this email directly or view it on GitHub.

@ghost
Copy link

ghost commented Feb 23, 2015

Woah. Just a question since it seems to be in a good place for merging and there hasn't been any activity in about a week. The reason I ask is because none of my counter caches are working on production. Thanks.

@radar
Copy link
Collaborator

radar commented Feb 23, 2015

I will review this when I have time.

Currently time is very limited as I get up at 6:30 every morning to get to work on time at 8:30. Then I work until 5:30 and get the train home for 20 minutes, where I work on my Rails 4 in Action book. There are no seats on the train in the morning to work on the book. After that, I don't do any more work unless my wife is at music class, which happens only on Tuesday nights. I would rather spend time with her than work. Weekends are out because of reasons I outlined in my last reply, and if I do have spare time on the weekend then it's going to go into Rails 4 in Action or just, you know, not working above my limits and burning out like I did at the end of 2009 quite horribly. It took months to recover from that properly and I dread that happening again.

All my spare time is going to work on Rails 4 in Action. Maintaining paranoia (or any of my other gems) is not a priority for me right now. When I get a spare moment, I will review this PR myself and then merge it in. For the time being, your patience is appreciated. If you are super keen to use this patch in production then use the fork until I have time to merge.

Counter caches on Rails 4.2 are broken anyway according to this comment from a user of Forem. Fix is supposed to be coming in 4.2.2. I don't know if this will/won't affect this PR.

So my questions to you @anthonycollini is: have you reviewed this pull request? Does it look shippable to you? Can you try using it in production and see if it does indeed fix your problem?

Thanks for your assistance and prompting.

@sergey-alekseev
Copy link
Contributor Author

@radar thanks for sharing. We appreciate your work on the open source projects and contributions to Rails! Personally I'm inspired by people like you.

@allaire
Copy link

allaire commented Mar 16, 2015

@sergey-alekseev We are currently using your branch version in our Gemfile while this get merged, thanks for your work!

@sergey-alekseev
Copy link
Contributor Author

@allaire my pleasure. I use my branch as well. :)

@ghost
Copy link

ghost commented Mar 17, 2015

I am also using this on production and it is working fine.

@pomartel
Copy link

Same here!

@radar
Copy link
Collaborator

radar commented Mar 18, 2015

That's enough verification. Thanks everyone :)

radar added a commit that referenced this pull request Mar 18, 2015
Fix counter cache behaviour on rails 4.2
@radar radar merged commit a37652f into rubysherpas:rails4 Mar 18, 2015
@radar
Copy link
Collaborator

radar commented Mar 18, 2015

Thanks @sergey-alekseev for the patience on this PR.

@thibaudgg
Copy link

Thanks @sergey-alekseev, thanks @radar!

@sergey-alekseev
Copy link
Contributor Author

My pleasure. Thanks for merging.

@joelbarker2011
Copy link

Thanks for the patch, @sergey-alekseev. I'm also using your before_restore code from Stack Overflow. In your OP on this thread, you said

Not sure whether #restore should increment counter cache back. In my current application I need it to be the same behaviour as it's now – don't increment counter cache after restore.

May I ask in what kind of situation you need the present behavior? In my current project, I'm using parent.children_count as a faster and easier cached value for parent.children.count (which is the whole purpose of the "counter cache", as I understand it). So it seems to me that the before_restore functionality should be the default. Having parent.children_count != parent.children.count seems terribly confusing.

(Sorry if I'm hijacking the thread; it seemed the most appropriate place to ask.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants