module Trestle class Admin require_relative "admin/builder" def initialize(context=nil) @context = context end # Delegate all missing methods to corresponding class method if available def method_missing(name, *args, &block) if self.class.respond_to?(name) self.class.send(name, *args, &block) else super end end def respond_to_missing?(name, include_private=false) self.class.respond_to?(name, include_private) || super end class << self attr_accessor :menu attr_accessor :form attr_writer :options attr_writer :breadcrumb def options @options ||= {} end def tables @tables ||= {} end def hooks @hooks ||= Hook::Set.new end # Deprecated: Use `tables[:index]` instead def table tables[:index] end # Deprecated: Use `tables[:index]=` instead def table=(table) tables[:index] = table end def breadcrumbs Breadcrumb::Trail.new(Array(Trestle.config.root_breadcrumbs) + [breadcrumb].compact) end def breadcrumb if @breadcrumb Breadcrumb.cast(@breadcrumb.call) elsif actions.include?(:index) default_breadcrumb end end def default_breadcrumb deprecated = I18n.t(:"admin.breadcrumbs.#{i18n_key}", default: human_admin_name) label = translate("breadcrumbs.index", default: deprecated) Breadcrumb.new(label, path) end def admin_name name.underscore.sub(/_admin$/, '') end def i18n_key admin_name end def human_admin_name translate("name", default: default_human_admin_name) end def default_human_admin_name name.demodulize.underscore.sub(/_admin$/, '').titleize end def translate(key, options={}) defaults = [:"admin.#{i18n_key}.#{key}", :"admin.#{key}"] defaults << options[:default] if options[:default] I18n.t(defaults.shift, **options.merge(default: defaults)) end alias t translate def parameter_name unscope_path(admin_name.singularize) end def route_name "#{admin_name.tr('/', '_')}_admin" end attr_writer :view_path def view_path @view_path || default_view_path end def default_view_path "admin/#{name.underscore.sub(/_admin$/, '')}" end def view_path_prefixes [view_path] end def controller_namespace "#{name.underscore}/admin" end def path(action=root_action, options={}) Engine.routes.url_for(options.merge(controller: controller_namespace, action: action, only_path: true)) end def to_param(*) raise NoMethodError, "#to_param called on non-resourceful admin. You may need to explicitly specify the admin." end def default_actions [:index] end def actions @actions ||= default_actions.dup end def root_action :index end def additional_routes @additional_routes ||= [] end def routes admin = self Proc.new do scope controller: admin.controller_namespace, path: admin.options[:path] || admin.admin_name do get "", action: "index", as: admin.route_name if admin.actions.include?(:index) admin.additional_routes.each do |block| instance_exec(&block) end end end end def railtie_routes_url_helpers(include_path_helpers=true) Trestle.railtie_routes_url_helpers(include_path_helpers) end def build(&block) Admin::Builder.build(self, &block) end def validate! # No validations by default. This can be overridden in subclasses. end private def unscope_path(path) path = path.to_s if i = path.rindex("/") path[(i + 1)..-1] else path end end end # This delegate call is deferred until the class method is defined, # since the method signature is different from Object#to_param. delegate :to_param, to: :class end end