Skip to content

Commit

Permalink
Load Solidus engine extension files automatically
Browse files Browse the repository at this point in the history
By cleanly separating extension files for the different Solidus
engines, we can only load solidus_backend files when the engine
itself is available rather than doing it all the time.

In turn, this allows extensions to only actually require the parts
of Solidus that they really need.
  • Loading branch information
aldesantis committed Jan 31, 2020
1 parent 128fd45 commit 3bdaf27
Showing 1 changed file with 47 additions and 12 deletions.
59 changes: 47 additions & 12 deletions lib/solidus_support/engine_extensions/decorators.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,68 @@ module SolidusSupport
module EngineExtensions
module Decorators
def self.included(engine)
engine.extend ClassMethods

engine.class_eval do
extend ClassMethods
config.to_prepare(&method(:activate).to_proc)

enable_solidus_engine_support('backend') if SolidusSupport.backend_available?
enable_solidus_engine_support('frontend') if SolidusSupport.frontend_available?
enable_solidus_engine_support('api') if SolidusSupport.api_available?
end
end

module ClassMethods
def activate
base_path = root.join('app/decorators')

if Rails.respond_to?(:autoloaders) && Rails.autoloaders.main
# Add decorators folder to the Rails autoloader. This
# allows Zeitwerk to resolve decorators paths correctly,
# when used.
Dir.glob(base_path.join('*')) do |decorators_folder|
# Add decorators folder to the Rails autoloader. This tells Zeitwerk to treat paths
# such as app/decorators/controllers as roots.
solidus_decorators_root.glob('*') do |decorators_folder|
Rails.autoloaders.main.push_dir(decorators_folder)
end
end

# Load decorator files. This is needed since they are
# never explicitely referenced in the application code
# and won't be loaded by default. We need them to be
# executed anyway to extend exisiting classes.
Dir.glob(base_path.join('**/*.rb')) do |decorator_path|
load_solidus_decorators_from(solidus_decorators_root)
end

# Loads decorator files.
#
# This is needed since they are never explicitly referenced in the application code and
# won't be loaded by default. We need them to be executed regardless in order to decorate
# existing classes.
def load_solidus_decorators_from(path)
path.glob('**/*.rb') do |decorator_path|
require_dependency(decorator_path)
end
end

private

# Returns the root for this engine's decorators.
#
# @return [Path]
def solidus_decorators_root
root.join('app/decorators')
end

# Enables support for a Solidus engine.
#
# This will simply tell Rails to load lib/controllers/[engine] and lib/views/[engine], as
# well as loading the decorators from lib/decorators/[engine].
#
# @see #load_solidus_decorators_from
def enable_solidus_engine_support(engine)
paths['app/controllers'] << "lib/controllers/#{engine}"
paths['app/views'] << "lib/views/#{engine}"

engine_context = self
config.to_prepare do
engine_context.instance_eval do
path = root.join("lib/decorators/#{engine}")
load_solidus_decorators_from(path)
end
end
end
end
end
end
Expand Down

0 comments on commit 3bdaf27

Please sign in to comment.