lib/chanko/loader.rb
require "pathname"
module Chanko
module Loader
class MissingEagarLoadSettingError < StandardError; end
class << self
delegate :load, :cache, :eager_load_units!, to: "loader"
end
def self.loader
zeitwerk? ? ZeitwerkLoader : ClassicLoader
end
def self.zeitwerk?
Rails.respond_to?(:autoloaders) && Rails.autoloaders.zeitwerk_enabled?
end
def self.classic?
!zeitwerk?
end
def self.prepare_eager_load(mode: )
if mode == :zeitwerk && zeitwerk?
self.loader.prepare_eager_load
elsif mode == :classic && classic?
self.loader.prepare_eager_load
end
end
class ZeitwerkLoader
def self.load(name)
self.new(name).load
end
def self.cache
# backward compatibility
{ }
end
def self.eager_load_units!
# Zeitwerk load chanko units as default
end
def self.prepare_eager_load
add_unit_directory_to_eager_load_paths
Rails.autoloaders.main.collapse(Chanko::Config.units_directory_path + '/*')
Rails.autoloaders.main.ignore(Chanko::Config.units_directory_path + '/*/spec*')
end
def self.add_unit_directory_to_eager_load_paths
path = Chanko::Config.units_directory_path
unless Rails.configuration.eager_load_paths.include?(path)
Rails.configuration.eager_load_paths << path
end
end
def initialize(name)
@name = name
end
def load
constantize
rescue NameError
# Chanko never raise error even if the constant fails to reference
false
end
def constantize
@name.to_s.camelize.constantize
end
end
class ClassicLoader
def self.cache
@cache ||= {}
end
def self.eager_load_units!
Pathname.glob("#{Chanko::Config.units_directory_path}/*").select(&:directory?).each do |path|
Chanko::Loader::ClassicLoader.load(path.basename.to_s.to_sym)
end
end
def self.prepare_eager_load
raise MissingEagarLoadSettingError if Rails.configuration.eager_load.nil?
if Rails.configuration.eager_load
ruleout_unit_files_from_rails_eager_loading
end
end
def self.ruleout_unit_files_from_rails_eager_loading
Rails.configuration.eager_load_paths.delete(Chanko::Config.units_directory_path)
end
def self.load(name)
self.new(name).load
end
def self.load_from_cache(name)
self.cache[name]
end
def self.save_to_cache(name, unit)
self.cache[name] = unit
end
def initialize(name)
@name = name
end
def load
load_from_cache.then do |unit|
next unit unless unit.nil?
load_from_file_and_store_to_cache
end
end
def load_from_file_and_store_to_cache
add_autoload_path
constantize.tap do |unit|
self.class.save_to_cache(@name, unit)
end
rescue Exception => exception
ExceptionHandler.handle(exception)
self.class.save_to_cache(@name, false)
false
end
def load_from_cache
self.class.load_from_cache(@name)
end
def add_autoload_path
ActiveSupport::Dependencies.autoload_paths << autoload_path
ActiveSupport::Dependencies.autoload_paths.uniq!
end
def autoload_path
"#{Config.units_directory_path }/#{@name}"
end
def constantize
@name.to_s.camelize.constantize
end
end
end
end