-
Notifications
You must be signed in to change notification settings - Fork 0
Backend Training: ActiveAdmin
🔖 activeadmin
, will_paginate
, kaminari
Now, we have all the frontend setup, let's move on to create an admin panel for us to manage the website. For this we will use activeadmin
which helps us easily come up with a systematic way of building admin panel.
Let's start by going to our admin panel at localhost:3000/admin
, and you should see...
We don't have an account for the admin panel yet. Let's create one.
$ rails c
irb(main):003:0> AdminUser.create!(email: '[email protected]', password: 'password', password_confirmation: 'password')
(0.1ms) BEGIN
AdminUser Exists (0.4ms) SELECT 1 AS one FROM "admin_users" WHERE "admin_users"."email" = $1 LIMIT $2 [["email", "[email protected]"], ["LIMIT", 1]]
SQL (1.5ms) INSERT INTO "admin_users" ("email", "encrypted_password", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["email", "[email protected]"], ["encrypted_password", "$2a$11$Js89SMyeLHkbO2Bpxh/v/Ovt2JzQslfyS5iFsr7Gz.9CL.DhaV4.2"], ["created_at", "2017-12-12 23:28:36.342152"], ["updated_at", "2017-12-12 23:28:36.342152"]]
(0.7ms) COMMIT
=> #<AdminUser id: 2, email: "[email protected]", created_at: "2017-12-12 23:28:36", updated_at: "2017-12-12 23:28:36">
Next, if you click on admin_user link you will get an error.
This is caused by will_paginate
and kaminari
since they are all using the same parameter for pagination.
To fix this we will create a kaminari config file.
# config/initializers/kaminari.rb
Kaminari.configure do |config|
config.page_method_name = :per_page_kaminari
end
Now, stop your server Control+c on your terminal window and start your server again..
$ rails s
Refresh the browser Command ⌘+r, and your page should display properly without any problems.
Now, let's login with this account, and you should see...
Great! Our admin panel is working. Now, let's fix the menus a bit to make it more organized.
# config/initializers/active_admin.rb
ActiveAdmin.setup do |config|
.....
# == Menu System
config.namespace :admin do |admin|
admin.build_menu do |menu|
menu.add label: proc { menu_label('Collection', icon: 'database') },
id: 'collections',
priority: 3
menu.add label: proc { menu_label('Forms', icon: 'email') },
id: 'forms',
priority: 5
menu.add label: proc { menu_label('Setting', icon: 'settings') },
id: 'settings',
priority: 99
end
admin.build_menu :utility_navigation do |menu|
menu.add label: proc { admin_menu_label(current_admin_user) },
id: 'current_admin_user',
priority: 2
menu.add label: proc { menu_label('Profile') },
id: 'profile',
url: proc { admin_admin_user_path(current_active_admin_user) },
priority: 1,
parent: 'current_admin_user'
menu.add label: proc { menu_label('Log Out') },
id: 'logout',
url: proc { destroy_admin_user_session_path },
priority: 2,
parent: 'current_admin_user'
end
end
......
Now, stop your server Control+c on your terminal window and start your server again..
$ rails s
Refresh the browser Command ⌘+r, and the end result should look like...
Great! We have added some nav menu to the menu. Let's fix dashboard and admin_user panel as well.
# app/admin/dashboard.rb
ActiveAdmin.register_page 'Dashboard' do
menu priority: 1,
label: proc { menu_label(I18n.t('active_admin.dashboard'), icon: 'chart-donut') }
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
# Here is an example of a simple dashboard with columns and panels.
#
# columns do
# column do
# panel "Recent Posts" do
# ul do
# Post.recent(5).map do |post|
# li link_to(post.title, admin_post_path(post))
# end
# end
# end
# end
# column do
# panel "Info" do
# para "Welcome to ActiveAdmin."
# end
# end
# end
end # content
end
# app/admin/admin_user.rb
ActiveAdmin.register AdminUser do
menu parent: 'settings', priority: 1
.....
end
Refresh the browser Command ⌘+r, and the end result should look like...
Great! Our dashboard looks more organized now. Let's move on to configuring our model resources.
ActiveAdmin strong params work like standard rails controller strong params.
Let's look at the app/admin/admin_user.rb
file. Here the strong params are defined with
permit_params :email, :password, :password_confirmation
Let's look at the app/admin/admin_user.rb
file. Here the index table is defined with
index do
selectable_column
id_column
column :email
column :current_sign_in_at
column :sign_in_count
column :created_at
actions
end
Let's look at the app/admin/admin_user.rb
file. Here the filters are defined with
filter :email
filter :current_sign_in_at
filter :sign_in_count
filter :created_at
Let's look at the app/admin/admin_user.rb
file. Here the form fields are defined with
form do |f|
f.inputs 'Admin Details' do
f.input :email
f.input :password
f.input :password_confirmation
end
f.actions
end
Now, we have looked at how to build out the admin pages for a model. Let's go ahead and add our admin pages for faq, contact, and news.
# app/models/faq.rb
class Faq < ApplicationRecord
....
def display_name
question.truncate(20)
end
end
# app/decorators/faq_decorator.rb
# Decorates Faqs
class FaqDecorator < ApplicationDecorator
delegate_all
end
# app/decorators/admin/faq_decorator.rb
# Decorates Faq for AA
class Admin::FaqDecorator < FaqDecorator
decorates :faq
def question_with_link
link_to truncate(question, length: 20), [:edit, :admin, object]
end
end
# app/admin/faq.rb
ActiveAdmin.register Faq do
decorate_with Admin::FaqDecorator
menu parent: 'collections',
priority: 5
config.sort_order = 'position_asc'
permit_params :question, :answer, :position
actions :all, except: %i[show]
# INDEX
filter :question
filter :answer
filter :position
filter :created_at
filter :updated_at
index do
selectable_column
column :position
column :question, :question_with_link, sortable: 'question'
column :updated_at
actions(dropdown: true, dropdown_name: nil)
end
# FORM
form do |f|
f.semantic_errors(*f.object.errors.keys)
f.inputs t('.faq.panel.detail', model: Faq.model_name.human) do
f.input :position
f.input :question
f.input :answer,
input_html: { class: 'tinymce' }
end
f.actions
end
end
# app/decorators/faq_decorator.rb
# Decorates Faqs
class FaqDecorator < ApplicationDecorator
delegate_all
end
# app/decorators/admin/faq_decorator.rb
# Decorates Faq for AA
class Admin::FaqDecorator < FaqDecorator
decorates :faq
def question_with_link
link_to truncate(question, length: 20), [:edit, :admin, object]
end
end
# app/admin/faq.rb
ActiveAdmin.register Faq do
decorate_with Admin::FaqDecorator
menu parent: 'collections',
priority: 5
config.sort_order = 'position_asc'
permit_params :question, :answer, :position
actions :all, except: %i[show]
# INDEX
filter :question
filter :answer
filter :position
filter :created_at
filter :updated_at
index do
selectable_column
column :position
column :question, :question_with_link, sortable: 'question'
column :updated_at
actions(dropdown: true, dropdown_name: nil)
end
# FORM
form do |f|
f.semantic_errors(*f.object.errors.keys)
f.inputs t('.faq.panel.detail', model: Faq.model_name.human) do
f.input :position
f.input :question
f.input :answer,
input_html: { class: 'tinymce' }
end
f.actions
end
end
# app/decorators/admin/post_decorator.rb
# Decorates Post for AA
class Admin::PostDecorator < PostDecorator
decorates :post
def title_with_link
link_to title, [:edit, :admin, object]
end
end
# app/admin/post.rb
ActiveAdmin.register Post do
decorate_with Admin::PostDecorator
menu parent: 'collections',
priority: 1
# STRONG PARAMS
permit_params :title, :content, :slug, :published_date, :published,
category_list: []
actions :all, except: %i[show]
# CONTROLLER
controller do
defaults finder: :find_by_slug
end
# INDEX
filter :title
filter :categories, input_html: { class: 'select2' }
filter :published, input_html: { class: 'select2' }
filter :published_date
filter :created_at
filter :updated_at
index do
selectable_column
column :title, :title_with_link, sortable: 'title'
column :published_date
column :updated_at
actions(dropdown: true, dropdown_name: nil)
end
# FORM
form do |f|
f.inputs t('.post.panel.detail', model: Post.model_name.human(count: 1)) do
f.input :title
f.input :slug
f.input :category_list,
as: :select,
collection: Post.category_counts.map(&:name),
multiple: true,
include_blank: false,
input_html: {
class: 'select2',
data: {
'select2-search' => true,
'select2-other' => true
}
}
f.input :content,
input_html: { class: 'tinymce' }
f.input :published_date
f.input :published
end
f.actions
end
end
Let's commit and move on...
$ git add -A
$ git commit -m 'ActiveAdmin Setup'