lib/hanami/slice_registrar.rb in hanami-2.1.0.beta2.1 vs lib/hanami/slice_registrar.rb in hanami-2.1.0.rc1

- old
+ new

@@ -44,24 +44,21 @@ slices.freeze super end def load_slices - slice_configs = Dir[root.join(CONFIG_DIR, SLICES_DIR, "*#{RB_EXT}")] - .map { |file| File.basename(file, RB_EXT) } + slice_configs = root.join(CONFIG_DIR, SLICES_DIR).glob("*#{RB_EXT}") + .map { _1.basename(RB_EXT) } - slice_dirs = Dir[File.join(root, SLICES_DIR, "*")] - .select { |path| File.directory?(path) } - .map { |path| File.basename(path) } + slice_dirs = root.join(SLICES_DIR).glob("*") + .select(&:directory?) + .map { _1.basename } - slice_names = (slice_dirs + slice_configs).uniq.sort + (slice_dirs + slice_configs).uniq.sort .then { filter_slice_names(_1) } + .each(&method(:load_slice)) - slice_names.each do |slice_name| - load_slice(slice_name) - end - self end def each(&block) slices.each_value(&block) @@ -95,41 +92,69 @@ def parent_slice_namespace parent.eql?(parent.app) ? Object : parent.namespace end - # Runs when a slice file has been found at `config/slices/[slice_name].rb`, or a slice directory - # at `slices/[slice_name]`. Attempts to require the slice class, if defined, before registering - # the slice. If a slice class is not found, registering the slice will generate the slice class. + # Runs when a slice file has been found inside the app at `config/slices/[slice_name].rb`, + # or when a slice directory exists at `slices/[slice_name]`. + # + # If a slice definition file is found by `find_slice_require_path`, then `load_slice` will + # require the file before registering the slice class. + # + # If a slice class is not found, registering the slice will generate the slice class. def load_slice(slice_name) - slice_require_path = root.join(CONFIG_DIR, SLICES_DIR, slice_name).to_s - begin - require(slice_require_path) - rescue LoadError => e - raise e unless e.path == slice_require_path - end + slice_require_path = find_slice_require_path(slice_name) + require slice_require_path if slice_require_path - slice_module_name = inflector.camelize("#{parent_slice_namespace.name}#{PATH_DELIMITER}#{slice_name}") slice_class = begin - inflector.constantize("#{slice_module_name}#{MODULE_DELIMITER}Slice") + inflector.constantize("#{slice_module_name(slice_name)}#{MODULE_DELIMITER}Slice") rescue NameError => e raise e unless e.name.to_s == inflector.camelize(slice_name) || e.name.to_s == :Slice end register(slice_name, slice_class) end + # Finds the path to the slice's definition file, if it exists, in the following order: + # + # 1. `config/slices/[slice_name].rb` + # 2. `slices/[parent_slice_name]/config/[slice_name].rb` (unless parent is the app) + # 3. `slices/[slice_name]/config/slice.rb` + # + # If the slice is nested under another slice then it will look in the following order: + # + # 1. `config/slices/[parent_slice_name]/[slice_name].rb` + # 2. `slices/[parent_slice_name]/config/[slice_name].rb` + # 3. `slices/[parent_slice_name]/[slice_name]/config/slice.rb` + def find_slice_require_path(slice_name) + app_slice_file_path = [slice_name] + app_slice_file_path.prepend(parent.slice_name) unless parent.eql?(parent.app) + ancestors = [ + parent.app.root.join(CONFIG_DIR, SLICES_DIR, app_slice_file_path.join(File::SEPARATOR)), + parent.root.join(CONFIG_DIR, SLICES_DIR, slice_name), + root.join(SLICES_DIR, slice_name, CONFIG_DIR, "slice") + ] + + ancestors + .uniq + .find { _1.sub_ext(RB_EXT).file? } + &.to_s + end + def build_slice(slice_name, &block) - slice_module_name = inflector.camelize("#{parent_slice_namespace.name}#{PATH_DELIMITER}#{slice_name}") slice_module = begin - inflector.constantize(slice_module_name) + inflector.constantize(slice_module_name(slice_name)) rescue NameError parent_slice_namespace.const_set(inflector.camelize(slice_name), Module.new) end slice_module.const_set(:Slice, Class.new(Hanami::Slice, &block)) + end + + def slice_module_name(slice_name) + inflector.camelize("#{parent_slice_namespace.name}#{PATH_DELIMITER}#{slice_name}") end def configure_slice(slice_name, slice) slice.instance_variable_set(:@parent, parent)