forked from solidusio/solidus
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a generator to create an initializer with new defaults
Following the work done in solidusio#4064, this commits introduces a Rails generator that creates a new initializer called, by default, `new_solidus_defaults.rb`. This initializer works in a very similar way that [`new_framework_defaults.rb` does in Rails](https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#configure-framework-defaults). It allows users to preview the defaults that have changed on a new Solidus version, as they are printed one by one on a commented line. Users can then keep enabling them while updating their application code. The main difference with the Rails system is that the `load_defaults` call is added to the initializer instead of the main configuration file (it would be the `spree.rb` initializer in our case). Users can remove it altogether when they're done with the process. The reason is that in our case, the `loaded_defaults` instance variable of the application configurations defaults to the last version, so it's not needed anymore when the process is done. In contrast, calling `load_defaults` in Rails changes the defaults imperatively to the new values (so it defaults to the outdated ones). For now, we're leaving this as a generator, but we could reference it from a rake task, although probably there's no need. Be aware that users need to provide the version from which they are updating. It's an option that offers more flexibility, as users can update from versions different from the latest one. It also plays well with our system's flexibility, for instance, to change defaults between a pre-release and a release. However, we can add some code to default to the latest minor version, but we should keep that information in our code, and that's a small burden for our update process.
- Loading branch information
1 parent
b897ecc
commit 4495d56
Showing
5 changed files
with
330 additions
and
0 deletions.
There are no files selected for viewing
26 changes: 26 additions & 0 deletions
26
core/lib/generators/solidus/update/templates/config/initializers/new_solidus_defaults.rb.tt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# This initializer lets you preview the defaults that have changed on the new | ||
# Solidus version. | ||
# | ||
# It allows you to enable them one by one while you adapt your application. | ||
# When you're done with all of them, you can safely remove this file. | ||
Spree.config do |config| | ||
<%= @core_changes %> | ||
end | ||
|
||
<% if defined?(Spree::Frontend::Engine) -%> | ||
Spree::Frontend::Config.configure do |config| | ||
<%= @frontend_changes %> | ||
end | ||
<% end -%> | ||
|
||
<% if defined?(Spree::Backend::Engine) -%> | ||
Spree::Backend::Config.configure do |config| | ||
<%= @backend_changes %> | ||
end | ||
<% end -%> | ||
|
||
<% if defined?(Spree::Api::Engine) -%> | ||
Spree::Api::Config.configure do |config| | ||
<%= @api_changes %> | ||
end | ||
<% end -%> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spree/core/preference_changes_between_solidus_versions' | ||
require 'rails/generators' | ||
|
||
module Solidus | ||
class UpdateGenerator < ::Rails::Generators::Base | ||
desc 'Generates a new initializer to preview the new defaults for current Solidus version' | ||
|
||
source_root File.expand_path('templates', __dir__) | ||
|
||
class_option :from, | ||
type: :string, | ||
banner: 'The version your are updating from. E.g. 2.11.10' | ||
|
||
class_option :initializer_basename, | ||
type: :string, | ||
default: 'new_solidus_defaults', | ||
banner: 'The name for the new initializer' | ||
|
||
class_option :to, | ||
type: :string, | ||
default: Spree.solidus_version, | ||
hide: true | ||
|
||
class_option :initializer_directory, | ||
type: :string, | ||
default: 'config/initializers/', | ||
hide: true | ||
|
||
def create_new_defaults_initializer | ||
from = options[:from] | ||
to = options[:to] | ||
@from = from | ||
@core_changes = core_changes_template(from, to) | ||
@frontend_changes = frontend_changes_template(from, to) | ||
@backend_changes = backend_changes_template(from, to) | ||
@api_changes = api_changes_template(from, to) | ||
|
||
template 'config/initializers/new_solidus_defaults.rb.tt', | ||
File.join(options[:initializer_directory], "#{options[:initializer_basename]}.rb") | ||
end | ||
|
||
private | ||
|
||
def core_changes_template(from, to) | ||
changes_template_for(Spree::AppConfiguration, from, to) | ||
end | ||
|
||
def frontend_changes_template(from, to) | ||
return '' unless defined?(Spree::Frontend::Engine) | ||
|
||
changes_template_for(Spree::FrontendConfiguration, from, to) | ||
end | ||
|
||
def backend_changes_template(from, to) | ||
return '' unless defined?(Spree::Backend::Engine) | ||
|
||
changes_template_for(Spree::BackendConfiguration, from, to) | ||
end | ||
|
||
def api_changes_template(from, to) | ||
return '' unless defined?(Spree::Api::Engine) | ||
|
||
changes_template_for(Spree::ApiConfiguration, from, to) | ||
end | ||
|
||
def changes_template_for(klass, from, to) | ||
changes = Spree::Core::PreferenceChangesBetweenSolidusVersions.new(klass).call(from: from, to: to) | ||
return '# No changes' if changes.empty? | ||
|
||
[ | ||
["config.load_defaults('#{from}')"] + | ||
changes.map do |pref_key, change| | ||
" # config.#{pref_key} = #{change[:to]}" | ||
end.flatten | ||
].join("\n") | ||
end | ||
end | ||
end |
28 changes: 28 additions & 0 deletions
28
core/lib/spree/core/preference_changes_between_solidus_versions.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# frozen_string_literal: true | ||
|
||
module Spree | ||
module Core | ||
class PreferenceChangesBetweenSolidusVersions | ||
attr_reader :config_class | ||
|
||
def initialize(config_class) | ||
@config_class = config_class | ||
end | ||
|
||
def call(from:, to:) | ||
preferences_from = config_class.new.load_defaults(from) | ||
preferences_to = config_class.new.load_defaults(to) | ||
preferences_from.reduce({}) do |changes, (pref_key, value_from)| | ||
value_to = preferences_to[pref_key] | ||
if value_from == value_to | ||
changes | ||
else | ||
changes.merge( | ||
pref_key => { from: value_from, to: value_to } | ||
) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
169 changes: 169 additions & 0 deletions
169
core/spec/lib/generators/solidus/update/update_generator_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
require 'generators/solidus/update/update_generator' | ||
|
||
RSpec.describe Solidus::UpdateGenerator do | ||
let(:initializer_directory) { Rails.root.join('tmp') } | ||
let(:initializer) { File.join(initializer_directory, 'new_solidus_defaults.rb') } | ||
let(:delete_initializer) { proc { File.delete(initializer) if File.exists?(initializer) }} | ||
let(:invoke) do | ||
lambda do |from, to| | ||
Rails::Generators.invoke('solidus:update', [ | ||
"--initializer_directory=#{Rails.root.join('tmp')}", | ||
"--from=#{from}", | ||
"--to=#{to}", | ||
"--quiet" | ||
]) | ||
end | ||
end | ||
|
||
before { delete_initializer.call } | ||
after { delete_initializer.call } | ||
|
||
context 'core' do | ||
it 'adds changes when present' do | ||
config_class = Class.new(Spree::Preferences::Configuration) do | ||
preference :foo, :boolean, default: by_version(true, '3.0' => false) | ||
end | ||
stub_const('Spree::AppConfiguration', config_class) | ||
|
||
invoke.('2.0', '3.0') | ||
|
||
expect(File.read(initializer)).to include( | ||
<<~RUBY | ||
Spree.config do |config| | ||
config.load_defaults('2.0') | ||
# config.foo = false | ||
end | ||
RUBY | ||
) | ||
end | ||
|
||
it "informs about no changes if there're none" do | ||
config_class = Class.new(Spree::Preferences::Configuration) | ||
stub_const('Spree::AppConfiguration', config_class) | ||
|
||
invoke.('2.0', '3.0') | ||
|
||
expect(File.read(initializer)).to include( | ||
<<~RUBY | ||
Spree.config do |config| | ||
# No changes | ||
end | ||
RUBY | ||
) | ||
end | ||
end | ||
|
||
context 'frontend' do | ||
before { stub_const('Spree::Frontend::Engine', true) } | ||
|
||
it 'adds changes when present' do | ||
config_class = Class.new(Spree::Preferences::Configuration) do | ||
preference :foo, :boolean, default: by_version(true, '3.0' => false) | ||
end | ||
stub_const('Spree::FrontendConfiguration', config_class) | ||
|
||
invoke.('2.0', '3.0') | ||
|
||
expect(File.read(initializer)).to include( | ||
<<~RUBY | ||
Spree::Frontend::Config.configure do |config| | ||
config.load_defaults('2.0') | ||
# config.foo = false | ||
end | ||
RUBY | ||
) | ||
end | ||
|
||
it "informs about no changes if there're none" do | ||
config_class = Class.new(Spree::Preferences::Configuration) | ||
stub_const('Spree::FrontendConfiguration', config_class) | ||
|
||
invoke.('2.0', '3.0') | ||
|
||
expect(File.read(initializer)).to include( | ||
<<~RUBY | ||
Spree::Frontend::Config.configure do |config| | ||
# No changes | ||
end | ||
RUBY | ||
) | ||
end | ||
end | ||
|
||
context 'backend' do | ||
before { stub_const('Spree::Backend::Engine', true) } | ||
|
||
it 'adds changes when present' do | ||
config_class = Class.new(Spree::Preferences::Configuration) do | ||
preference :foo, :boolean, default: by_version(true, '3.0' => false) | ||
end | ||
stub_const('Spree::BackendConfiguration', config_class) | ||
|
||
invoke.('2.0', '3.0') | ||
|
||
expect(File.read(initializer)).to include( | ||
<<~RUBY | ||
Spree::Backend::Config.configure do |config| | ||
config.load_defaults('2.0') | ||
# config.foo = false | ||
end | ||
RUBY | ||
) | ||
end | ||
|
||
it "informs about no changes if there're none" do | ||
config_class = Class.new(Spree::Preferences::Configuration) | ||
stub_const('Spree::BackendConfiguration', config_class) | ||
|
||
invoke.('2.0', '3.0') | ||
|
||
expect(File.read(initializer)).to include( | ||
<<~RUBY | ||
Spree::Backend::Config.configure do |config| | ||
# No changes | ||
end | ||
RUBY | ||
) | ||
end | ||
end | ||
|
||
context 'api' do | ||
before { stub_const('Spree::Api::Engine', true) } | ||
|
||
it 'adds changes when present' do | ||
config_class = Class.new(Spree::Preferences::Configuration) do | ||
preference :foo, :boolean, default: by_version(true, '3.0' => false) | ||
end | ||
stub_const('Spree::ApiConfiguration', config_class) | ||
|
||
invoke.('2.0', '3.0') | ||
|
||
expect(File.read(initializer)).to include( | ||
<<~RUBY | ||
Spree::Api::Config.configure do |config| | ||
config.load_defaults('2.0') | ||
# config.foo = false | ||
end | ||
RUBY | ||
) | ||
end | ||
|
||
it "informs about no changes if there're none" do | ||
config_class = Class.new(Spree::Preferences::Configuration) | ||
stub_const('Spree::ApiConfiguration', config_class) | ||
|
||
invoke.('2.0', '3.0') | ||
|
||
expect(File.read(initializer)).to include( | ||
<<~RUBY | ||
Spree::Api::Config.configure do |config| | ||
# No changes | ||
end | ||
RUBY | ||
) | ||
end | ||
end | ||
end |
27 changes: 27 additions & 0 deletions
27
core/spec/lib/spree/core/preference_changes_between_solidus_versions_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
require 'spree/core/preference_changes_between_solidus_versions' | ||
require 'spree/preferences/configuration' | ||
|
||
RSpec.describe Spree::Core::PreferenceChangesBetweenSolidusVersions do | ||
it 'includes defaults that have changed' do | ||
config_class = Class.new(Spree::Preferences::Configuration) do | ||
preference :foo, :boolean, default: by_version(true, '3.0' => false) | ||
end | ||
|
||
changes = described_class.new(config_class).call(from: '2.0', to: '3.0') | ||
|
||
expect(changes).to include(foo: { from: true, to: false }) | ||
end | ||
|
||
it "doesn't include defaults that have not changed" do | ||
config_class = Class.new(Spree::Preferences::Configuration) do | ||
preference :foo, :boolean, default: by_version(true, '3.0' => false) | ||
end | ||
|
||
changes = described_class.new(config_class).call(from: '2.0', to: '2.5') | ||
|
||
expect(changes.keys).not_to include(:foo) | ||
end | ||
end |