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

Accept static_model_preferences class name as string #4070

Closed
wants to merge 1 commit into from
Closed

Accept static_model_preferences class name as string #4070

wants to merge 1 commit into from

Conversation

willianveiga
Copy link
Contributor

Description
Make it possible to accept static_model_preferences class name as string.

Fixes #4040

Checklist:

  • I have followed Pull Request guidelines
  • I have added a detailed description into each commit message
  • I have updated Guides and README accordingly to this change (if needed)
  • I have added tests to cover this change (if needed)
  • I have attached screenshots to this PR for visual changes (if needed)

@kennyadsl
Copy link
Member

Thanks @willianveiga, this looks good but I'd like to better understand why we need this (as asked in the original issue).

I mean, in which circumstances we need to use a string there?

Copy link
Member

@elia elia left a comment

Choose a reason for hiding this comment

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

Hey @willianveiga! thanks for tackling this 💯
I left a couple of comments for possible issues with the proposed implementation 👍

@@ -36,9 +36,14 @@ def initialize
end

def add(klass, name, preferences)
constantized_klass = klass.try(:constantize) || klass
Copy link
Member

Choose a reason for hiding this comment

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

This will trigger an autoload during initialization, which is one of the things that this change should avoid. Thoughts on just converting to a string if it's not already and allowing Definition to accept it as well?

Copy link
Contributor

Choose a reason for hiding this comment

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

Hey @elia, I'm wondering how to fix it. In the end, add creates another Definition instance, and it calls .defined_preferences on the class 🤷

@@ -5,7 +5,7 @@
module Spree
RSpec.describe Preferences::StaticModelPreferences do
let(:preference_class) do
Class.new do
MyFakeStaticModelPreferencesClass ||= Class.new do
Copy link
Member

Choose a reason for hiding this comment

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

I think defining a constant here will actually define it under Spree::, an alternative could be using stubbed constants https://rspec.info/blog/2012/06/constant-stubbing-in-rspec-2-11/, but I'm not sure it's a good one, you need to check how they'll interact with this setup.

@waiting-for-dev
Copy link
Contributor

Hey @willianveiga, would you like to retake it? It's very close to a final solution 🍾

waiting-for-dev added a commit to nebulab/solidus that referenced this pull request Jul 13, 2022
This is how we usually recommend configuring sources for static
preferences [1]:

```ruby
Spree.config do |config|
  config.static_model_preferences.add(
    AmazingStore::AmazingPaymentMethod,
    'amazing_payment_method_credentials',
    credentials: ENV['AMAZING_PAYMENT_METHOD_CREDENTIALS'],
    server: Rails.env.production? ? 'production' : 'test',
    test_mode: !Rails.env.production?
  )
end
```

However, it's no longer possible to directly reference an autoloadable
class from an initializer [2].

In this case, we can't change the `#add` method to take the class name
instead. The reason is that it ends up invoking a sanitization check on
the given preferences against the defined preferences, and that, of
course, needs access to the actual class [3].

Therefore, it's better to start recommending nesting the configuration
within a `.to_prepare` block, as they run every time the code is
reloaded [4]:

```ruby
Rails.application.config.to_prepare do
  Spree::Config.static_model_preferences.add(
    AmazingStore::AmazingPaymentMethod,
    'amazing_payment_method_credentials',
    credentials: ENV['AMAZING_PAYMENT_METHOD_CREDENTIALS'],
    server: Rails.env.production? ? 'production' : 'test',
    test_mode: !Rails.env.production?
  )
end
```

However, that means running the `#add` method multiple times, so we need
to change it to replace the definition instead of raising an error.

[1] - https://github.com/solidusio/solidus_stripe/blob/3fab36511a9d02ebd64d03571704ac5a9031b63b/README.md#usage
[2] - https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#autoload-on-boot-and-on-each-reload
[3] - https://github.com/solidusio/solidus/blob/df51df62fa9b829216958b21b20514b7a3d87b30/core/lib/spree/preferences/static_model_preferences.rb#L13
[4] - https://guides.rubyonrails.org/configuring.html#initialization-events

Closes solidusio#4070 & solidusio#4040
waiting-for-dev added a commit to nebulab/solidus that referenced this pull request Jul 15, 2022
This is how we usually recommend configuring sources for static
preferences [1]:

```ruby
Spree.config do |config|
  config.static_model_preferences.add(
    AmazingStore::AmazingPaymentMethod,
    'amazing_payment_method_credentials',
    credentials: ENV['AMAZING_PAYMENT_METHOD_CREDENTIALS'],
    server: Rails.env.production? ? 'production' : 'test',
    test_mode: !Rails.env.production?
  )
end
```

However, it's no longer possible to directly reference an autoloadable
class from an initializer [2].

In this case, we can't change the `#add` method to take the class name
instead. The reason is that it ends up invoking a sanitization check on
the given preferences against the defined preferences, and that, of
course, needs access to the actual class [3].

Therefore, it's better to start recommending nesting the configuration
within a `.to_prepare` block, as they run every time the code is
reloaded [4]:

```ruby
Rails.application.config.to_prepare do
  Spree::Config.static_model_preferences.add(
    AmazingStore::AmazingPaymentMethod,
    'amazing_payment_method_credentials',
    credentials: ENV['AMAZING_PAYMENT_METHOD_CREDENTIALS'],
    server: Rails.env.production? ? 'production' : 'test',
    test_mode: !Rails.env.production?
  )
end
```

However, that means running the `#add` method multiple times, so we need
to change it to replace the definition instead of raising an error.

[1] - https://github.com/solidusio/solidus_stripe/blob/3fab36511a9d02ebd64d03571704ac5a9031b63b/README.md#usage
[2] - https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#autoload-on-boot-and-on-each-reload
[3] - https://github.com/solidusio/solidus/blob/df51df62fa9b829216958b21b20514b7a3d87b30/core/lib/spree/preferences/static_model_preferences.rb#L13
[4] - https://guides.rubyonrails.org/configuring.html#initialization-events

Closes solidusio#4070 & solidusio#4040
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.

static_model_preferences doesn't accept class-names as strings, interfering with autoloading
4 participants