Skip to content

Commit

Permalink
Adds a generator to create an initializer with new defaults
Browse files Browse the repository at this point in the history
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.

We're adding the `load_defaults` call with the old version value to the
generated initializer. Users can remove the file altogether when they're
done with the process. At that point, we require them to add
`load_defaults` with the new version to the main initializer file
(`spree.rb`). Even if there's no actual need for that, as
`loaded_defaults` on the configuration class defaults to the current
Solidus version, we want to enforce that so that users are on the safe
side for the next version upgrade. If they don't add it, we emit a
warning.

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
waiting-for-dev committed Jun 18, 2021
1 parent 63501e7 commit 144ab8d
Show file tree
Hide file tree
Showing 22 changed files with 450 additions and 30 deletions.
2 changes: 1 addition & 1 deletion api/Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ task default: :spec
DummyApp::RakeTasks.new(
gem_root: File.expand_path(__dir__),
lib_name: 'solidus_api'
)
) { Spree::Api::Config.load_defaults(Spree.solidus_version) }

task test_app: 'db:reset'
4 changes: 4 additions & 0 deletions api/lib/spree/api/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ class Engine < Rails::Engine
# Leave initializer empty for backwards-compatibility. Other apps
# might still rely on this event.
initializer "spree.api.environment", before: :load_config_initializers do; end

config.after_initialize do
Spree::Api::Config.check_load_defaults_called('Spree::Api::Config')
end
end
end
end
2 changes: 1 addition & 1 deletion api/spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
DummyApp.setup(
gem_root: File.expand_path('..', __dir__),
lib_name: 'solidus_api'
)
) { Spree::Api::Config.load_defaults(Spree.solidus_version) }

require 'rails-controller-testing'
require 'rspec/rails'
Expand Down
5 changes: 4 additions & 1 deletion backend/Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ task default: [:spec, 'spec:js']
DummyApp::RakeTasks.new(
gem_root: File.expand_path(__dir__),
lib_name: 'solidus_backend'
)
) do
Spree::Backend::Config.load_defaults(Spree.solidus_version)
Spree::Api::Config.load_defaults(Spree.solidus_version)
end

task :teaspoon do
require 'teaspoon'
Expand Down
4 changes: 4 additions & 0 deletions backend/lib/spree/backend/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ class Engine < ::Rails::Engine
# Leave initializer empty for backwards-compatability. Other apps
# might still rely on this event.
initializer "spree.backend.environment", before: :load_config_initializers do; end

config.after_initialize do
Spree::Backend::Config.check_load_defaults_called('Spree::Backend::Config')
end
end
end
end
5 changes: 4 additions & 1 deletion backend/spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
DummyApp.setup(
gem_root: File.expand_path('..', __dir__),
lib_name: 'solidus_backend'
)
) do
Spree::Backend::Config.load_defaults(Spree.solidus_version)
Spree::Api::Config.load_defaults(Spree.solidus_version)
end

require 'rails-controller-testing'
require 'rspec-activemodel-mocks'
Expand Down
2 changes: 1 addition & 1 deletion bin/build-ci
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class Project
end

def run_teaspoon
cmd = %w[bundle exec teaspoon] + teaspoon_arguments
cmd = %w[RAILS_ENV=test bundle exec teaspoon] + teaspoon_arguments

run_test_cmd(cmd)
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 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 and add
# the updated `load_defaults` calls to the top of the config blocks in your
# Solidus main initializer.

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 -%>
80 changes: 80 additions & 0 deletions core/lib/generators/solidus/update/update_generator.rb
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ Bundler.require(*Rails.groups(assets: %w(development test)))
require '<%= lib_name %>'

<%= application_definition %>

7 changes: 7 additions & 0 deletions core/lib/spree/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ def self.config(&_block)
end

module Core
def self.solidus_installed?
Rails.application.paths['config/initializers'].paths.any? do |path|
File.exists?(path.join('spree.rb'))
end ||
(Rails.env.test? && Rails.application.class.name == 'DummyApp::Application')
end

class GatewayError < RuntimeError; end
end
end
Expand Down
4 changes: 4 additions & 0 deletions core/lib/spree/core/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ class Engine < ::Rails::Engine
app.config.action_mailer.preview_path = "{#{original_preview_path},#{solidus_preview_path}}"
ActionMailer::Base.preview_path = app.config.action_mailer.preview_path
end

config.after_initialize do
Spree::Config.check_load_defaults_called('Spree::Config')
end
end
end
end
28 changes: 28 additions & 0 deletions core/lib/spree/core/preference_changes_between_solidus_versions.rb
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
17 changes: 17 additions & 0 deletions core/lib/spree/preferences/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,35 @@ class Configuration
# defaults. Set via {#load_defaults}
attr_reader :loaded_defaults

attr_reader :load_defaults_called

def initialize
@loaded_defaults = Spree.solidus_version
@load_defaults_called = false
end

# @param [String] Solidus version from which take defaults when not
# overriden.
# @see #load_defaults
def load_defaults(version)
@loaded_defaults = version
@load_defaults_called = true
reset
end

def check_load_defaults_called(instance_constant_name = nil)
return if load_defaults_called || !Spree::Core.solidus_installed?

target_name = instance_constant_name || "#{self.class.name}.new"
Spree::Deprecation.warn <<~MSG
Please, indicate wich Solidus version defaults the application must use.
The method `#{target_name}.load_defaults` must be called from the Solidus initializer. E.g.:
config.load_defaults('#{Spree.solidus_version}')
MSG
end

# @yield [config] Yields this configuration object to a block
def configure
yield(self)
Expand Down
4 changes: 3 additions & 1 deletion core/lib/spree/testing_support/dummy_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ module ApplicationHelper

# @private
module DummyApp
def self.setup(gem_root:, lib_name:, auto_migrate: true)
def self.setup(gem_root:, lib_name:, auto_migrate: true, &block)
ENV["LIB_NAME"] = lib_name
DummyApp::Application.config.root = File.join(gem_root, 'spec', 'dummy')
block.call if block_given?

DummyApp::Application.initialize!

Expand Down Expand Up @@ -127,6 +128,7 @@ class Application < ::Rails::Application

Spree.user_class = 'Spree::LegacyUser'
Spree.config do |config|
config.load_defaults(Spree.solidus_version)
config.mails_from = "[email protected]"

if ENV['DISABLE_ACTIVE_STORAGE']
Expand Down
5 changes: 3 additions & 2 deletions core/lib/spree/testing_support/dummy_app/rake_tasks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ module DummyApp
class RakeTasks
include Rake::DSL

def initialize(gem_root:, lib_name:)
def initialize(gem_root:, lib_name:, &block)
task :dummy_environment do
ENV['RAILS_ENV'] = 'test'
require lib_name
require 'spree/testing_support/dummy_app'
DummyApp.setup(
gem_root: gem_root,
lib_name: lib_name,
auto_migrate: false
auto_migrate: false,
&block
)
end
end
Expand Down
Loading

0 comments on commit 144ab8d

Please sign in to comment.