Multiple Namespaces with ActiveAdmin

A step by step guide on how to manage multiple namespaces in ActiveAdmin

Alberto Negron true
06-14-2019

Active Admin is a Ruby on Rails gem for building administrative interfaces. There are plenty of tutorials out there showing how to customize the look & fill with the default namespace: AdminUser.

This tutorial will provide guidelines on how-to multiple interfaces using namespaces. Imaging you having administrators, agents and suppliers in your rails app and each group required different views and level of access to your application.

Disclaimer: This post shows how I came up with a solution to managing multiple namespaces but it might no be the best approach or the solution you need! Consider yourself warned.

Our admin interface will have 2 areas:

Add gems to gemfile:


#admin
gem 'activeadmin'
gem 'devise', '~>4.6.0'

Run bundle install

Create an AdminUser class to use with ActiveAdmin:

bin/rails g active_admin:install

We get an alert on a few things we need to do before continuing:

Ensure you have defined root_url to something in your config/routes.rb

Let’s create a dummy controller for now.

bin/rails g controller home index

and routes.rb should looks like:


Rails.application.routes.draw do
  root to: 'home#index'
  get 'home/index'
  devise_for :admin_users, ActiveAdmin::Devise.config
  ActiveAdmin.routes(self)
end

Now, migrate and seed your database before starting the server:


bin/rails db:migrate
bin/rails db:seed
bin/rails server

Visit http://localhost:3000/admin and log in as the default user:


User: admin@example.com
Password: password

Note: if you havent configure mailer when devise was installed you may want to do:

Possible configuration for config/environments/development.rb:

config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

AdminSupplier

Create devise model:

bin/rails g devise AdminSupplierUser bin/rails db:migrate

Create SupplierAdminUser & password in seeds.rb

Note comment out AdminUser.create! before running


AdminSupplierUser.create!(email: 'supplier@example.com', password: 'password', password_confirmation: 'password') if Rails.env.development?

bin/rails db:seed

Create directory in app/admin_supplier

update config/initializers/active_admin.rb as follow:


 config.site_title = "ActiveAdmin MultiNamespaces"

  config.load_paths = [File.expand_path('app/admin', Rails.root), File.expand_path('app/admin_supplier', Rails.root)]

  config.default_namespace = :admin

config.namespace :admin do |admin|
  admin.site_title = "Admin Panel"
  admin.authentication_method = :authenticate_admin_user!
  admin.current_user_method = :current_admin_user
  admin.logout_link_path = :destroy_admin_user_session_path
end

config.namespace :supplier do |supplier|
  supplier.site_title = "Active Supplier Panel"
  supplier.authentication_method = :authenticate_admin_supplier_user!
  supplier.current_user_method = :current_admin_supplier_user
  supplier.logout_link_path = :destroy_admin_supplier_user_session_path
end

Update routes.rb


Rails.application.routes.draw do

  root to: 'home#index'
  get 'home/index'

  devise_for :admin_users, ActiveAdmin::Devise.config
  devise_for :admin_supplier_users,ActiveAdmin::Devise.config.merge({path: '/supplier'})
  ActiveAdmin.routes(self)
end

Create app/admin_supplier/dashboard.rb


ActiveAdmin.register_page "Dashboard", namespace: :admin_supplier do
  menu priority: 1, label: proc { I18n.t("active_admin.dashboard") }

  content title: proc { I18n.t("active_admin.dashboard") } do
    div class: "blank_slate_container", id: "dashboard_default_message" do
      span class: "blank_slate" do
        span I18n.t("active_admin.dashboard_welcome.welcome")
        small I18n.t("active_admin.dashboard_welcome.call_to_action")
      end
    end

  end # content
end

By now you should have your 2 interfaces up and running at:

One more thing you need to do is to redirect supplier logout to the supplier path as currently it will default to the Admin login page.

Create app/admin_supplier/override.rb with the following snippet:


ActiveAdmin::Devise::SessionsController.class_eval do
  def after_sign_out_path_for(resource)
    case resource
    when :admin_supplier_user then supplier_root_url
    else super
  end
  end
end

This will override the default method when the resource is :admin_supplier_user.

And that’s it - hope you find it helpful.

I guess another approach is using cancan gem that is probably a subject for a completely different post!!!

Reuse

Text and figures are licensed under Creative Commons Attribution CC BY 4.0. The figures that have been reused from other sources don't fall under this license and can be recognized by a note in their caption: "Figure from ...".

Citation

For attribution, please cite this work as

Negron (2019, June 14). Data Addict's Secret Diary: Multiple Namespaces with ActiveAdmin. Retrieved from http://www.dataaddict.me/posts/2019-06-14-multiple-namespaces-with-activeadmin/

BibTeX citation

@misc{negron2019multiple,
  author = {Negron, Alberto},
  title = {Data Addict's Secret Diary: Multiple Namespaces with ActiveAdmin},
  url = {http://www.dataaddict.me/posts/2019-06-14-multiple-namespaces-with-activeadmin/},
  year = {2019}
}