lib/hanami/slice_registrar.rb in hanami-2.0.0.beta4 vs lib/hanami/slice_registrar.rb in hanami-2.0.0.rc1
- old
+ new
@@ -1,13 +1,13 @@
# frozen_string_literal: true
require_relative "constants"
-require_relative "slice"
module Hanami
# @api private
class SliceRegistrar
+ VALID_SLICE_NAME_RE = /^[a-z][a-z0-9_]+$/
SLICE_DELIMITER = CONTAINER_KEY_DELIMITER
attr_reader :parent, :slices
private :parent, :slices
@@ -15,18 +15,20 @@
@parent = parent
@slices = {}
end
def register(name, slice_class = nil, &block)
+ unless name.to_s =~ VALID_SLICE_NAME_RE
+ raise ArgumentError, "slice name #{name.inspect} must be lowercase alphanumeric text and underscores only"
+ end
+
return unless filter_slice_names([name]).any?
if slices.key?(name.to_sym)
raise SliceLoadError, "Slice '#{name}' is already registered"
end
- # TODO: raise error unless name meets format (i.e. single level depth only)
-
slice = slice_class || build_slice(name, &block)
configure_slice(name, slice)
slices[name.to_sym] = slice
@@ -42,12 +44,10 @@
slices.freeze
super
end
def load_slices
- return self unless root
-
slice_configs = Dir[root.join(CONFIG_DIR, SLICES_DIR, "*#{RB_EXT}")]
.map { |file| File.basename(file, RB_EXT) }
slice_dirs = Dir[File.join(root, SLICES_DIR, "*")]
.select { |path| File.directory?(path) }
@@ -75,11 +75,13 @@
slices.values
end
def with_nested
to_a.flat_map { |slice|
- [slice] + slice.slices.with_nested
+ # Return nested slices first so that their more specific namespaces may be picked up first
+ # by SliceConfigurable#slice_for
+ slice.slices.with_nested + [slice]
}
end
private
@@ -89,39 +91,42 @@
def inflector
parent.inflector
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,
- # or generates a new slice class for the given slice name.
+ 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.
def load_slice(slice_name)
- slice_const_name = inflector.camelize(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_module_name = inflector.camelize("#{parent_slice_namespace.name}#{PATH_DELIMITER}#{slice_name}")
slice_class =
begin
- inflector.constantize("#{slice_const_name}::Slice")
+ inflector.constantize("#{slice_module_name}#{MODULE_DELIMITER}Slice")
rescue NameError => e
- raise e unless e.name.to_s == slice_const_name || e.name.to_s == :Slice
+ raise e unless e.name.to_s == inflector.camelize(slice_name) || e.name.to_s == :Slice
end
register(slice_name, slice_class)
end
def build_slice(slice_name, &block)
+ slice_module_name = inflector.camelize("#{parent_slice_namespace.name}#{PATH_DELIMITER}#{slice_name}")
slice_module =
begin
- slice_module_name = inflector.camelize(slice_name.to_s)
inflector.constantize(slice_module_name)
rescue NameError
- Object.const_set(inflector.camelize(slice_module_name), Module.new)
+ parent_slice_namespace.const_set(inflector.camelize(slice_name), Module.new)
end
slice_module.const_set(:Slice, Class.new(Hanami::Slice, &block))
end