module ActiveAdmin::NestedNamespace
Constants
- VERSION
Public Class Methods
find_for_resource_in_namespace(resource, name)
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 123 def self.find_for_resource_in_namespace(resource, name) where( resource_type: resource_type(resource), resource_id: resource, namespace: name.to_s ).order(ActiveAdmin.application.namespaces[ActiveAdmin.application.build_name_path(name)].comments_order) end
new(application, name)
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 58 def initialize(application, name) @application = application @name_path = ActiveAdmin.application.build_name_path(name) @resources = ResourceCollection.new register_module unless root? build_menu_collection end
setup()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 5 def self.setup ActiveAdmin::Application.class_eval do def namespace(name) name ||= :root namespace = namespaces[build_name_path(name)] ||= begin namespace = Namespace.new(self, name) ActiveSupport::Notifications.publish ActiveAdmin::Namespace::RegisterEvent, namespace namespace end yield(namespace) if block_given? namespace end def build_name_path(name) Array(name).map(&:to_s).map(&:underscore).map(&:to_sym) end end ActiveAdmin::BaseController.class_eval do def authenticate_active_admin_user if active_admin_namespace.authentication_method auth_method = active_admin_namespace.authentication_method if auth_method.is_a?(Proc) namespace = active_admin_namespace.name_path send(auth_method.call(namespace)) else send(auth_method) end end end def current_active_admin_user if active_admin_namespace.current_user_method user_method = active_admin_namespace.current_user_method if user_method.is_a?(Proc) namespace = active_admin_namespace.name_path send(user_method.call(namespace)) else send(user_method) end end end end ActiveAdmin::Namespace.class_eval do attr_reader :name_path def initialize(application, name) @application = application @name_path = ActiveAdmin.application.build_name_path(name) @resources = ResourceCollection.new register_module unless root? build_menu_collection end def name Deprecation.warn "name replaced by name_path now that namespaces can be nested." name_path.first end def root? name_path.first == :root end def module_name root? ? nil : name_path.map(&:to_s).map(&:camelize).join('::') end def route_prefix root? ? nil : name_path.map(&:to_s).join('_').underscore end def add_logout_button_to_menu(menu, priority = 20, html_options = {}) computed_logout_link_path = logout_link_path.is_a?(Proc) ? logout_link_path.call(name_path) : logout_link_path if computed_logout_link_path html_options = html_options.reverse_merge(method: logout_link_method || :get) menu.add id: 'logout', priority: priority, html_options: html_options, label: -> {I18n.t 'active_admin.logout'}, url: computed_logout_link_path, if: :current_active_admin_user? end end # dynamically create nested modules def register_module module_names = module_name.split("::").inject([]) {|n, c| n << (n.empty? ? [c] : [n.last] + [c]).flatten} module_names.each do |module_name_array| eval "module ::#{module_name_array.join("::")}; end" end end end ActiveAdmin::Namespace::Store.class_eval do def [](key) @namespaces[Array(key)] end def names Deprecation.warn "names replaced by name_paths now that namespaces can be nested." @namespaces.keys.first end def name_paths @namespaces.keys end end ActiveAdmin::Comment.class_eval do def self.find_for_resource_in_namespace(resource, name) where( resource_type: resource_type(resource), resource_id: resource, namespace: name.to_s ).order(ActiveAdmin.application.namespaces[ActiveAdmin.application.build_name_path(name)].comments_order) end end ActiveAdmin::Comments::Views::Comments.class_eval do def build(resource) @resource = resource @comments = ActiveAdmin::Comment.find_for_resource_in_namespace(resource, active_admin_namespace.name_path).includes(:author).page(params[:page]) super(title, for: resource) build_comments end def comments_url(*args) parts = [] parts << active_admin_namespace.name_path unless active_admin_namespace.root? parts << active_admin_namespace.comments_registration_name.underscore parts << 'path' send parts.join('_'), *args end def comment_form_url parts = [] parts << active_admin_namespace.name_path unless active_admin_namespace.root? parts << active_admin_namespace.comments_registration_name.underscore.pluralize parts << 'path' send parts.join '_' end end ActiveAdmin::Page.class_eval do def namespace_name Deprecation.warn "namespace_name replaced by namespace_name now that namespaces can be nested." namespace.name.to_s end def namespace_name_path namespace.name_path end end ActiveAdmin::Resource::BelongsTo::TargetNotFound.class_eval do def initialize(key, namespace) super "Could not find #{key} in #{namespace.name_path} " + "with #{namespace.resources.map(&:resource_name)}" end end ActiveAdmin::Router.class_eval do def define_root_routes(router) router.instance_exec @application.namespaces do |namespaces| namespaces.each do |namespace| if namespace.root? root namespace.root_to_options.merge(to: namespace.root_to) else proc = Proc.new do root namespace.root_to_options.merge(to: namespace.root_to, as: :root) end (namespace.name_path.reverse.inject(proc) {|n, c| Proc.new {namespace c, namespace.route_options.dup, &n}}).call end end end end # Defines the routes for each resource def define_resource_routes(router) router.instance_exec @application.namespaces, self do |namespaces, aa_router| resources = namespaces.flat_map {|n| n.resources.values} resources.each do |config| routes = aa_router.resource_routes(config) # Add in the parent if it exists if config.belongs_to? belongs_to = routes routes = Proc.new do # If it's optional, make the normal resource routes instance_exec &belongs_to if config.belongs_to_config.optional? # Make the nested belongs_to routes # :only is set to nothing so that we don't clobber any existing routes on the resource resources config.belongs_to_config.target.resource_name.plural, only: [] do instance_exec &belongs_to end end end # Add on the namespace if required unless config.namespace.root? nested = routes routes = Proc.new do proc = Proc.new do instance_exec &nested end (config.namespace.name_path.reverse.inject(proc) {|n, c| Proc.new {namespace c, config.namespace.route_options.dup, &n}}).call end end instance_exec &routes end end end end ActiveAdmin::Scope.class_eval do def initialize(name, method = nil, options = {}, &block) @name, @scope_method = name, method.try(:to_sym) if name.is_a? Proc raise "A string/symbol is required as the second argument if your label is a proc." unless method @id = ActiveAdmin::Dependency.rails.parameterize method.to_s else @scope_method ||= (name.is_a?(Array) ? name.join('_').underscore : name).to_sym @id = ActiveAdmin::Dependency.rails.parameterize name.to_s end @scope_method = nil if @scope_method == :all @scope_method, @scope_block = nil, block if block_given? @localizer = options[:localizer] @show_count = options.fetch(:show_count, true) @display_if_block = options[:if] || proc {true} @default_block = options[:default] || proc {false} end end ActiveAdmin::Views::Pages::Base.class_eval do def add_classes_to_body @body.add_class(params[:action]) @body.add_class(params[:controller].tr('/', '_')) @body.add_class("active_admin") @body.add_class("logged_in") @body.add_class(active_admin_namespace.name_path.map(&:to_s).join('_') + '_namespace') end end # patch - active_admin/orm/active_record/comments.rb ActiveAdmin.after_load do |app| app.namespaces.each do |namespace| # Un-register default comment pages namespace.resources.instance_variable_get(:@collection).delete_if {|k,v| v.instance_variable_get(:@resource_class_name) == '::ActiveAdmin::Comment' } # Re-register comments pages with nested namespaces namespace.register ActiveAdmin::Comment, as: namespace.comments_registration_name do actions :index, :show, :create, :destroy menu namespace.comments ? namespace.comments_menu : false config.comments = false # Don't allow comments on comments config.batch_actions = false # The default destroy batch action isn't showing up anyway... scope :all, show_count: false # Register a scope for every namespace that exists. # The current namespace will be the default scope. app.namespaces.map(&:name_path).sort { |x,y| x[0] <=> y[0] }.each do |name_path| scope "/#{name_path.join('/')}", default: namespace.name_path == name_path do |scope| scope.where namespace: name_path.to_s end end # Store the author and namespace before_save do |comment| comment.namespace = active_admin_config.namespace.name_path comment.author = current_active_admin_user end controller do # Prevent N+1 queries def scoped_collection super.includes(:author, :resource) end # Redirect to the resource show page after comment creation def create create! do |success, failure| success.html do ActiveAdmin::Dependency.rails.redirect_back self, active_admin_root end failure.html do flash[:error] = I18n.t 'active_admin.comments.errors.empty_text' ActiveAdmin::Dependency.rails.redirect_back self, active_admin_root end end def destroy destroy! do |success, failure| success.html do ActiveAdmin::Dependency.rails.redirect_back self, active_admin_root end failure.html do ActiveAdmin::Dependency.rails.redirect_back self, active_admin_root end end end end end permit_params :body, :namespace, :resource_id, :resource_type index do column I18n.t('active_admin.comments.resource_type'), :resource_type column I18n.t('active_admin.comments.author_type'), :author_type column I18n.t('active_admin.comments.resource'), :resource column I18n.t('active_admin.comments.author'), :author column I18n.t('active_admin.comments.body'), :body column I18n.t('active_admin.comments.created_at'), :created_at actions end end end end end
Public Instance Methods
[](key)
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 107 def [](key) @namespaces[Array(key)] end
add_classes_to_body()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 258 def add_classes_to_body @body.add_class(params[:action]) @body.add_class(params[:controller].tr('/', '_')) @body.add_class("active_admin") @body.add_class("logged_in") @body.add_class(active_admin_namespace.name_path.map(&:to_s).join('_') + '_namespace') end
authenticate_active_admin_user()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 29 def authenticate_active_admin_user if active_admin_namespace.authentication_method auth_method = active_admin_namespace.authentication_method if auth_method.is_a?(Proc) namespace = active_admin_namespace.name_path send(auth_method.call(namespace)) else send(auth_method) end end end
build(resource)
click to toggle source
Calls superclass method
# File lib/active_admin/nested_namespace.rb, line 134 def build(resource) @resource = resource @comments = ActiveAdmin::Comment.find_for_resource_in_namespace(resource, active_admin_namespace.name_path).includes(:author).page(params[:page]) super(title, for: resource) build_comments end
build_name_path(name)
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 22 def build_name_path(name) Array(name).map(&:to_s).map(&:underscore).map(&:to_sym) end
comment_form_url()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 149 def comment_form_url parts = [] parts << active_admin_namespace.name_path unless active_admin_namespace.root? parts << active_admin_namespace.comments_registration_name.underscore.pluralize parts << 'path' send parts.join '_' end
comments_url(*args)
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 141 def comments_url(*args) parts = [] parts << active_admin_namespace.name_path unless active_admin_namespace.root? parts << active_admin_namespace.comments_registration_name.underscore parts << 'path' send parts.join('_'), *args end
create()
click to toggle source
Redirect to the resource show page after comment creation
# File lib/active_admin/nested_namespace.rb, line 305 def create create! do |success, failure| success.html do ActiveAdmin::Dependency.rails.redirect_back self, active_admin_root end failure.html do flash[:error] = I18n.t 'active_admin.comments.errors.empty_text' ActiveAdmin::Dependency.rails.redirect_back self, active_admin_root end end def destroy destroy! do |success, failure| success.html do ActiveAdmin::Dependency.rails.redirect_back self, active_admin_root end failure.html do ActiveAdmin::Dependency.rails.redirect_back self, active_admin_root end end end end
current_active_admin_user()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 41 def current_active_admin_user if active_admin_namespace.current_user_method user_method = active_admin_namespace.current_user_method if user_method.is_a?(Proc) namespace = active_admin_namespace.name_path send(user_method.call(namespace)) else send(user_method) end end end
define_resource_routes(router)
click to toggle source
Defines the routes for each resource
# File lib/active_admin/nested_namespace.rb, line 195 def define_resource_routes(router) router.instance_exec @application.namespaces, self do |namespaces, aa_router| resources = namespaces.flat_map {|n| n.resources.values} resources.each do |config| routes = aa_router.resource_routes(config) # Add in the parent if it exists if config.belongs_to? belongs_to = routes routes = Proc.new do # If it's optional, make the normal resource routes instance_exec &belongs_to if config.belongs_to_config.optional? # Make the nested belongs_to routes # :only is set to nothing so that we don't clobber any existing routes on the resource resources config.belongs_to_config.target.resource_name.plural, only: [] do instance_exec &belongs_to end end end # Add on the namespace if required unless config.namespace.root? nested = routes routes = Proc.new do proc = Proc.new do instance_exec &nested end (config.namespace.name_path.reverse.inject(proc) {|n, c| Proc.new {namespace c, config.namespace.route_options.dup, &n}}).call end end instance_exec &routes end end end
define_root_routes(router)
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 179 def define_root_routes(router) router.instance_exec @application.namespaces do |namespaces| namespaces.each do |namespace| if namespace.root? root namespace.root_to_options.merge(to: namespace.root_to) else proc = Proc.new do root namespace.root_to_options.merge(to: namespace.root_to, as: :root) end (namespace.name_path.reverse.inject(proc) {|n, c| Proc.new {namespace c, namespace.route_options.dup, &n}}).call end end end end
destroy()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 316 def destroy destroy! do |success, failure| success.html do ActiveAdmin::Dependency.rails.redirect_back self, active_admin_root end failure.html do ActiveAdmin::Dependency.rails.redirect_back self, active_admin_root end end end
module_name()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 75 def module_name root? ? nil : name_path.map(&:to_s).map(&:camelize).join('::') end
name()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 66 def name Deprecation.warn "name replaced by name_path now that namespaces can be nested." name_path.first end
name_paths()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 116 def name_paths @namespaces.keys end
names()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 111 def names Deprecation.warn "names replaced by name_paths now that namespaces can be nested." @namespaces.keys.first end
namespace(name) { |namespace| ... }
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 8 def namespace(name) name ||= :root namespace = namespaces[build_name_path(name)] ||= begin namespace = Namespace.new(self, name) ActiveSupport::Notifications.publish ActiveAdmin::Namespace::RegisterEvent, namespace namespace end yield(namespace) if block_given? namespace end
namespace_name()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 160 def namespace_name Deprecation.warn "namespace_name replaced by namespace_name now that namespaces can be nested." namespace.name.to_s end
namespace_name_path()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 165 def namespace_name_path namespace.name_path end
register_module()
click to toggle source
dynamically create nested modules
# File lib/active_admin/nested_namespace.rb, line 96 def register_module module_names = module_name.split("::").inject([]) {|n, c| n << (n.empty? ? [c] : [n.last] + [c]).flatten} module_names.each do |module_name_array| eval "module ::#{module_name_array.join("::")}; end" end end
root?()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 71 def root? name_path.first == :root end
route_prefix()
click to toggle source
# File lib/active_admin/nested_namespace.rb, line 79 def route_prefix root? ? nil : name_path.map(&:to_s).join('_').underscore end
scoped_collection()
click to toggle source
Prevent N+1 queries
Calls superclass method
# File lib/active_admin/nested_namespace.rb, line 300 def scoped_collection super.includes(:author, :resource) end