-
-
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
Allow storing static preferences using string class names #4858
Conversation
Codecov Report
@@ Coverage Diff @@
## master #4858 +/- ##
=======================================
Coverage 86.23% 86.24%
=======================================
Files 578 578
Lines 14674 14683 +9
=======================================
+ Hits 12654 12663 +9
Misses 2020 2020
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
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.
Thanks for working on it, @elia. That's something that needs to be addressed 🙌
However, did you happen to check if we will still render the error message on initialization, or otherwise, will it happen only for affected runtimes? Keeping the first behavior is optimal, as it saves from more headaches on production. If that changes, we could work around that by having one #to_prepare
block on our engine doing the sanitization check for all configured preferences.
What do you think?
@store = Hash.new do |data, klass| | ||
data[klass] = {} | ||
end | ||
@store = {} |
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 do think it's cleaner to create the Hash with a fresh hash as the default value, for a few reasons:
- Otherwise, we need to sanitize it every time we access a key, as we're doing now twice in
#add
&#fetch
. - Could break something in edge cases where code relies on returning a Hash.
- In my view, it communicates better as it nails down the data structure we need.
Thoughts?
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.
The reason I touched this is that while storing prefs for solidus_stripe I noticed that trying a non existing key would add the key to the hash, e.g.:
>> sp = Spree::Preferences::StaticModelPreferences.new
=> #<Spree::Preferences::StaticModelPreferences:0x00000001124dac70 @store={}>
>> sp.for_class("Foo")
=> {}
>> sp
=>
#<Spree::Preferences::StaticModelPreferences:0x00000001124dac70
@store={"Foo"=>{}}>
>>
I'll change it to a simpler Hash.new { {} }
so it behaves this way:
>> h = Hash.new { {} }
=> {}
>> h[:asdf]
=> {}
>> h
=> {}
>> h[:asdf] = 1234
=> 1234
>> h
=> {:asdf=>1234}
>>
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 had to walk back on this, my second example wasn't correct, and after all we only need to set the empty hash in #add
and fallback to a default in #for_class
which is not much.
The whole preferences system could probably be simplified but didn't want to launch into a campaign, and this will at least provide a consistent the experience within initializers.
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.
Hmm, I see. I never realized that Ruby had this behavior. What about the change in the API (i.e., returning nil
instead of Hash
? Do you think it's plausible it could break stores? cc @kennyadsl
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'd say that the whole API a bit sparse and could be streamlined, it also only serves one model inside solidus (although it's probably more across the ecosystem). But I wanted to surgically solve only the problem of not being able to pass strings for class names and finally make it consistent with other parts of the configuration.
There's also probably a case for making some of these APIs to be private and so not susceptible to backward compatibility support.
core/spec/models/spree/preferences/static_model_preferences_spec.rb
Outdated
Show resolved
Hide resolved
9418515
to
521aae9
Compare
Hey, @elia, it looks nice, but what do you think about:
|
521aae9
to
55b4df4
Compare
@waiting-for-dev sorry I though I addressed that! I updated the PR moving the check to a |
5280935
to
e7835f5
Compare
@@ -87,6 +87,7 @@ class Engine < ::Rails::Engine | |||
|
|||
config.after_initialize do | |||
Spree::Config.check_load_defaults_called('Spree::Config') | |||
Spree::Config.static_model_preferences.validate! |
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 if you set the preference value after the app is initialized? Do you need to call validate!
manually as well?
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.
After the app is initialized you could change the model configuration (e.g. adding or removing a preference) not the static preference value, but I regarded that as infrequent.
If we want to do it at every request in development we could move it to a to_prepare
block, would you prefer that?
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.
You are right, they live in memory and we can't change their value at runtime. At least, not easily and it's not an expected usage.
This will make unnecessary to wrap these definitions under `.to_prepare` blocks. Additionally the error message for unexpected keys has improved and now lists both all the unexpected keys along with the expected keys, mentioning the name associated to the definition.
e7835f5
to
8281f98
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.
❤️
Update the documentation for solidusio/solidus#4858
💔 Some backports could not be created
Manual backportTo create the backport manually run:
Questions ?Please refer to the Backport tool documentation and see the Github Action logs for details |
💔 Some backports could not be created
Manual backportTo create the backport manually run:
Questions ?Please refer to the Backport tool documentation and see the Github Action logs for details |
💔 Some backports could not be created
Manual backportTo create the backport manually run:
Questions ?Please refer to the Backport tool documentation and see the Github Action logs for details |
This will make unnecessary to wrap these definitions under `.to_prepare` blocks. Additionally the error message for unexpected keys has improved and now lists both all the unexpected keys along with the expected keys, mentioning the name associated to the definition. Backports solidusio#4858 to v3.1
There's no longer the need to call `.to_prepare`, as the issue has been fixed upstream: - v3.3: solidusio/solidus#4858 - v3.2: solidusio/solidus#4939 - v3.1: solidusio/solidus#4967
There's no longer the need to call `.to_prepare`, as the issue has been fixed upstream: - v3.3: solidusio/solidus#4858 - v3.2: solidusio/solidus#4939 - v3.1: solidusio/solidus#4967
Summary
This will make unnecessary to wrap these definitions under
.to_prepare
blocks.Additionally the error message for unexpected keys has improved and now lists both all the unexpected keys along with the expected keys, mentioning the name associated to the definition.
The only thing that changed is that it doesn't do so when the configuration is added but rather when it's fetched.Completes #4070 and addresses the original request of #4040.
Checklist
Check out our PR guidelines for more details.
The following are mandatory for all PRs:
The following are not always needed (
cross them outif they are not):