-
Notifications
You must be signed in to change notification settings - Fork 119
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 _changed? BC break and introduce algolia_dirty? method #338
Conversation
["#{attr_name}_changed?", "will_save_change_to_#{attr_name}?"].each do |method_name| | ||
if object.respond_to?(method_name) | ||
return object.send(method_name) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this code essentially always call #{attr_name}_changed?
, since on any random Rails model, calling model.respond_to?(:xxx_changed?)
returns true for all model attributes?
If so, this would essentially nullify #325, which means that on Rails 5.1 this gem would revert to its old behavior i.e. it would start emitting warnings again for all algolia attributes with the same name as a model attribute.
As a reminder, the deprecation warning in Rails 5.1 was:
DEPRECATION WARNING: The behavior of
attribute_changed?
inside of after callbacks will be changing in the next version of Rails. The new return value will reflect the behavior of calling the method aftersave
returned (e.g. the opposite of what it returns now). To maintain the current behavior, usesaved_change_to_attribute?
instead.
I believe this warning was removed in Rails 5.2 as they changed the behavior (I guess). But xxx_changed?
still exists and will likely always exist.
So unless there is some way to know if xxx_changed
was defined by the end user, instead of redefined by Rails, I am not sure this fix would work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree. I don't know why I didn't see it myself. I guess after trying a few things, I started ignoring some cases. I was really looking to restore the previous behavior. 😅
I definitely don't want to see those warning in more recent rails version 👍
What is the problem this PR is trying to fix? Is it to call Is it because people redefine
^ If the goal of this PR is to support this use case and only this use case (i.e. assuming people only define
|
I think you are handling this correctly 👍 There will be many apps that use <= rails 5.1 for years to come so it should be supported. There are maybe 20 ways to do this but... I think the loop to call both the methods is simple and good! If we try to be clever we just create edge cases!! 👍 for your implementation. |
Thank you @jeromedalbert and @simonireilly for your precious feedback, I really appreciate it 🙏 I looked for a better solution inspired by all @jeromedalbert's ideas. I think I found a fairly safe way to check whether rails_magic_def = object.method(method_name).source_location[0].end_with?("active_model/attribute_methods.rb") I think now, all the different scenario are handled, backward-compatibility is restored and deprecated method shouldn't be used. I'm going to add more tests to ensure that 👍 Again, any feedback is more than welcome. Thank you very much for helping me on this! |
Wow that is some Jedi-level code introspection right there. 😂 Looks good to me. |
Gemfile
Outdated
if defined?(RUBY_VERSION) && RUBY_VERSION == "1.8.7" | ||
gem 'ruby18_source_location' | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need that @julienbourdeau ? Doesn't seem to be a very popular library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
source_location
is only available after in ruby 1.9, this gem backports the feature to 1.8.
I thought __file__
should work with ruby < 1.9 but I got undefined method in Travis as well.
One other solution would be to not have this feature in Ruby < 1.9 and in this case we always call attr_changed?
method. In this case, people won't be able to use the new name but you can't run Rails 5 on ruby 1.8, I don't think it's important.
Now, that I think about it, It might be the best solution. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think always calling the attr_changed?
method is fine, it's what we've done before; no?
In this case, people won't be able to use the new name but you can't run Rails 5 on ruby 1.8, I don't think it's important.
Correct
Now, that I think about it, It might be the best solution. WDYT?
Most probably. Also, what you've done is not enough: the Gemfile
is handling the dependencies of the project, while the dependencies that are gonna be bundled while releasing the gem is defined in algoliasearch-rails.gemspec
. There should be a single mutualized list for both, but the fact we're having extra dependencies based on the ruby VM/versions makes it impossible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you Sylvain for reminding me about algoliasearch-rails.gemspec
. When writing this "fix" it totally went over my head 😅 🙏
0c9ae1c
to
f333911
Compare
c27d3eb
to
3ca72f5
Compare
source_location method were added in Ruby 1.9 we cannot figure out if the _changed? method was user-defined or if it's the automatic Rails method.
3ca72f5
to
bc07d06
Compare
Fix breaking change introduced in algolia#352 According to the [documentation](https://github.com/algolia/algoliasearch-rails/blob/master/lib/README.md#630), using custom attributes without a custom `_changed?` method will always cause changes to push to the API. This behavior was lost in algolia#338 Fix unexpected behavior during transactions algolia#353 `@algolia_must_reindex` is reset in every validate call. This means that a record that is updated multiple times in a transaction will only be indexed if the final update marks as must reindex. Update the code so that once `@algolia_must_reindex` is marked as `true`, it remains true until explicitly unset in `algolia_perform_index_tasks`
Fix breaking change introduced in algolia#352 According to the [documentation](https://github.com/algolia/algoliasearch-rails/blob/master/lib/README.md#630), using custom attributes without a custom `_changed?` method will always cause changes to push to the API. This behavior was lost in algolia#338 Fix unexpected behavior during transactions algolia#353 `@algolia_must_reindex` is reset in every validate call. This means that a record that is updated multiple times in a transaction will only be indexed if the final update marks as must reindex. Update the code so that once `@algolia_must_reindex` is marked as `true`, it remains true until explicitly unset in `algolia_perform_index_tasks`
Describe your change
We recently made some change to handle the new
will_save_change_to_#{attr}?
instead of the deprecated#{attr}_changed?
. See #325I didn't realize that this was breaking backward compat' because we check your ActiveRecord version. So if you upgrade, existing methods named
#{attr}_changed?
won't be called.I refactored it to the "first responding method", both will be tested, regardless of your Rails version. I added more tests for this.
algolia_dirty?
methodI added this in the same PR but it could be removed to merge the fix independantly. I added a method called
algolia_dirty?
, you can define it to override the calls to all _changed? method. I think this could be useful in case you need to define many _changed? method or to handle multiple relationships.Please any feedback on this one is appreciated 🙏
📝 DOC: Doc update is one the way.