-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Deprecate calling preferences without serialization #4013
Deprecate calling preferences without serialization #4013
Conversation
a91da40
to
48ee499
Compare
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 like this approach.
376870c
to
2a88e12
Compare
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.
Great stuff Martin! I only left some comments/questions but overall I think it's good to merge both in 2.11 and 3.0. If that was breaking your application, I think it's safe to consider this a patch.
2a88e12
to
dd8db61
Compare
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.
What about providing a module/concern for this? I'm not particularly interested in DRYing things, but if we need to make other changes in the future (eg. deprecate the way we serialize/initialize defaults) it could be handy.
I like that idea. Especially because that means we can have the callback and the after_initialize
call in the same file. Pretty nice!
dd8db61
to
2313219
Compare
17ca6d5
to
e3d47e4
Compare
This fixes an issue that arose because of commit b947015, which initialized the serialization of the preference column only if the respective subclass had any preferences defined. This is not always the case, and previous versions of Solidus would always allow a subclass of e.g. `Spree::Calculator` to access their `preferences` attribute as a Hash. The intention of the commit in question was to speed up initialization for models that do not have a preferences column. Instead of complex metamagic, this moves the initialization of the preferences column and preference defaults to those classes that actually needed, actually yielding MORE performance benefits, as `serialize` and the `after_initialize` hook are only called once, not once per preference being defined. For classes that expect Spree::Base to call `serialize`, this commit adds deprecation messaging and parsing to Spree::Base#preferences.
e3d47e4
to
9c472a9
Compare
8a97d6b
to
302b078
Compare
This removes even more code from Spree::Base, and groups the few lines of code that are needed for persisted preferences in one module.
The use of any of the methods in `Preferable` without `Persistable` makes no sense. Let's declutter Spree::Base some more!
The error message here calls for "persistable", because all objects that inherit from Spree::Base *actually* need the Persistable module.
If you try accessing a calculator with preferences in the DB, and that calculator hasn't seen the `serialize` call, Rails will try accessing the preferences column directly and return a string :(
These methods aren't available automatically any longer, thanks to Rails 6.1. They actually weren't in the first place, because not every model has a `preferences` column.
302b078
to
167299e
Compare
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 left a non-blocking comment, let me know your thoughts but I'm fine merging even as is.
Thanks!
end | ||
|
||
before(:each) do | ||
allow(Spree::Deprecation).to receive(:warn). |
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.
What about turning this into an expect
? The concern is that it may not be emitting the deprecation warning when we expect this happens. I mean, stubbing the deprecation should not be used to avoid failures and clean the logs only but to actually test that users get a deprecation message.
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 can't do that, because on the second test that runs, the method will already be defined and an expect
would fail. Undoing that include
turns out to be a lot of 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.
Got it, and I can't think at a clean way to do it.
I like this change and what it's doing. Thanks for the contribution Martin! |
Description
In Solidus < 2.11.4,
Spree::Base
had aserialize :preferences, Hash
statement. This statement fails in Rails 6.1ff, as after that Rails will try deserializing the column even if it isn't there.What this commit does is:
serialize
call fromSpree::Base
, as many inheriting classes do not have apreferences
columnserialize
andafter_initialize
call to those base classes that need itSpree::Calculator
Spree::PromotionAction
Spree::PaymentMethod
Spree::PromotionRule
preferences
getter toSpree::Base
that exhibits the following behaviour: Ifpreferences
is not a Hash, we can safely assume that the class of the instance we're trying to get preferences from expectsSpree::Base
to perform theserialize
call for them. In that case, callserialize
on the instance's class, ensuring that all future loads of this type of object will havepreferences
serialized, and parse the attribute usingActiveRecord::Type::Serialized
(as that's howSpree::Base
worked).preferences_coder_class
method. I don't think it's prudent to add an extension point here for something that was hardcoded in the past and can easily be circumnavigated by e.g. setting one's custom class to serialize using JSON:This PR goes against the
v2.11
branch of Solidus; I would like to uphold my PR #3997 for themaster
branch.This means that the deprecation window for this change would be
v2.11.8
=>v3.0.0
, but I think that's doable. There is a bit of work in related projects, but it just consists in adding to lines to configuration classes.Checklist:
I have updated Guides and README accordingly to this change (if needed)II have attached screenshots to this PR for visual changes (if needed)