module Scrivito # # @api private # class ModelLibrary attr_reader :custom_pages, :custom_widgets, :custom_paths def initialize @custom_pages, @custom_widgets, @custom_paths = [], [], [] end # # Clears model cache. # # @api private # @see Scrivito.models # def clear_cache @pages = nil @widgets = nil @paths = nil end # # Configures which models Scrivito assumes as pages and widgets. # # @api private # @see Scrivito.models # def define(&block) DSL.new(self).instance_eval(&block) end # # Lists available page models. # # @api private # @see Scrivito.models # @return [Scrivito::ClassCollection] available page classes # def pages @pages ||= load_models('page', Scrivito::BasicObj) end # # Lists available widget models. # # @api private # @see Scrivito.models # @return [Scrivito::ClassCollection] available widget classes # def widgets @widgets ||= load_models('widget', Scrivito::BasicWidget) end # # Lists available paths to scan for models. # # @api private # @see Scrivito.models # @return [Array] available paths to scan for models. # def paths @paths ||= (autoload_model_paths + custom_paths).map(&:to_s) end private def load_models(type, base_class) model_classes = load_models_from_paths(type, base_class) + load_custom_models(type, base_class) ClassCollection.new(model_classes.compact) end def load_models_from_paths(type, base_class) paths.map { |path| load_models_from_path(type, path, base_class) }.flatten end def load_models_from_path(type, path, base_class) Dir["#{path}/**/*_#{type}.rb"].map do |file_path| load_model(file_path.gsub(path, '').gsub('.rb', '').classify, base_class) end end def load_model(class_name, base_class) model_class = class_name.constantize model_class if model_class.ancestors.include?(base_class) rescue NameError end def load_custom_models(type, base_class) send("custom_#{type}s").map do |class_name| load_model(class_name, base_class) end end def autoload_model_paths ActiveSupport::Dependencies.autoload_paths.select do |path| path.to_s.ends_with?('/app/models') end end class DSL < Struct.new(:model_library) def page(*names) model_library.custom_pages.push(*names) end def widget(*names) model_library.custom_widgets.push(*names) end def paths model_library.custom_paths end end end end