ActiveAdminのメニュー設定を便利にする ActiveAdmin::MenuTree というgemを作ったのでご紹介します。
ActiveAdminとは
ActiveAdminとは、Railsで管理画面をさくっと作れるフレームワークですね。とても便利です。
ここではActiveAdmin自体についてはある程度知っている(使ったことがある)前提として話を進めます。
なお、ActiveAdmin v2.10.0 時点の情報になります。
ActiveAdminのメニューはカスタマイズできる
さて、これをお読みいただいているみなさまは、ActiveAdminのメニューをカスタマイズする方法はご存知でしょうか。
ActiveAdminでは、リソースを作ればデフォルトで何もしなくてもメニューに表示されるので、小規模プロジェクトだと気にならずにそのまま使っている場合も多いかもしれません。
しかし、少し規模が大きくなってリソースの数が増えてくると、どこに何があるかわかりづらくなりますよね。
何もしないとこんな感じになってしまう
こういうふうにカスタマイズできます
グループ化したり、順番を入れ替えたり、好きなラベルを設定したりできます。
このように、ActiveAdminではメニューをある程度カスタマイズする方法が提供されています。
ActiveAdmin公式のメニューカスタマイズ方法
まずはActiveAdminでできるメニューカスタマイズの方法をご紹介します。
公式ドキュメントに書いてある内容をベースに紹介します。
ActiveAdminの各リソースでmenuメソッドを使う
まず、ActiveAdminの各リソースでmenu
メソッドに引数を渡すのが基本的な設定方法になります。
たとえば、menuメソッドにfalse
を渡すことで特定のリソースでメニューを無効にでき、そのリソースがメニューに表示されなくなります。
もちろんページ自体はなくならないので、パスを開けばアクセスできます。
# app/admin/post.rb
ActiveAdmin.register Post do
menu false
end
menuメソッドで使える4つのオプション
menu
メソッドでは以下の4つのオプションによってメニューをカスタマイズできます。
-
:label
- 文字列かprocでメニューに表示するラベルを設定できる -
:parent
- 文字列IDかラベルで親メニューを指定できる(ネストさせることができる) -
:if
- ブロックかメソッドのシンボルでメニューを表示するかどうか制御できる -
:priority
- 数値で優先度を設定できる(デフォルトは10)
ここではpriority
とparent
を中心に紹介します。
Menu Priority
-
prioriy
でメニューの優先度を設定できます - 数値が小さいほど左側に表示されます
- 数値が同じ場合は名前順になります
- デフォルトは10
ActiveAdmin.register Post do
menu priority: 1
end
Drop Down Menus
-
parent
で親メニューを設定することで、メニューをグループ化できます - 指定した
parent
(以下の例のBlog
)は、存在しなければ自動で作られます
ActiveAdmin.register Post do
menu parent: "Blog"
end
- 配列で指定するとさらにネストできます
ActiveAdmin.register Post do
menu parent: ["Admin", "Blog"]
end
Customizing Parent Menu Items
- 親メニューをカスタマイズする場合はイニシャライザで設定します
- 通常の
menu
と同じオプションが使えます - 子メニューからは
parent
で同じラベル名(またはid)を指定することで識別します
# config/initializers/active_admin.rb
config.namespace :admin do |admin|
admin.build_menu do |menu|
menu.add label: "Blog", priority: 0
end
end
# app/admin/post.rb
ActiveAdmin.register Post do
menu parent: "Blog"
end
Dynamic Parent Menu Items
- 親メニューのラベルを動的にしたい場合は、
id
を設定すれば子メニューから参照できます
# config/initializers/active_admin.rb
config.namespace :admin do |admin|
admin.build_menu do |menu|
menu.add id: "blog", label: proc{ "Something dynamic" }, priority: 0
end
end
# app/admin/post.rb
ActiveAdmin.register Post do
menu parent: "blog"
end
ここが不便だよActiveAdmin
以上のように、ActiveAdminではメニューのカスタマイズが可能なのですが、主に以下の2点が少し不便だと思っています。
-
priority
での順序管理- 一度設定したメニューの順番を変更する場合、各リソースの
priority
を一つずつ変更する必要がある - adminリソースのファイルはメニューの順番に並んでるわけではないので、どれがどれだかわからなくなる
- 一度設定したメニューの順番を変更する場合、各リソースの
-
parent
での階層関係の管理- 親メニューをカスタマイズするにはイニシャライザで設定する必要がある
ひとことで言うと、設定が各リソースファイルに分散していて変更が面倒です。
特に親メニューと通常のメニューが混在して順序を管理したい場合などに顕著になると思います。
そこで ActiveAdmin::MenuTree
ActiveAdmin::MenuTree を使えば、前述の不便な点を解消して、メニューをyamlで直感的に管理できます。
ActiveAdmin::MenuTree の使い方
ここからようやく ActiveAdmin::MenuTree の使い方の紹介になります。
インストール
インストールは普通にgemを追加するだけ。
# Gemfile
gem 'activeadmin-menu_tree'
# インストール
$ bundle install
使い方はたった2ステップ!
かんたんです。
1. menu_tree の設定
yamlで設定を書いて、イニシャライザで読み込む。
# config/activeadmin-menu_tree.yml or anywhere you like
activeadmin:
menu_tree:
- id: Dashboard
- label: Admin
children:
- id: AdminUser
label: Admin Users
- id: Comment
label: Admin Comments
# config/initializers/activeadmin-menu_tree.rb
ActiveAdmin::MenuTree.setup do |config|
config.menu_tree = YAML.load_file(Rails.root.join("config/activeadmin-menu_tree.yml"))["activeadmin"]["menu_tree"]
end
2. ActiveAdminの各リソースで menu_tree を呼び出す
通常はmenu
メソッドで設定しているところをmenu_tree
に変更
# app/admin/admin_users.rb
ActiveAdmin.register AdminUser do
menu_tree
# ...
end
# app/admin/dashboard.rb
ActiveAdmin.register_page "Dashboard" do
menu_tree label: proc { I18n.t("active_admin.dashboard") }
# ...
end
-
priority
/parent
は設定不要になるので消してOK -
menu
メソッドと同様のオプションを渡せるので、label
やif
はそのまま動的に設定可能
これでRailsを起動すればメニューがいい感じに設定されています
その他の設定読み込み方法
また、ActiveAdmin::MenuTreeでは、yamlを使わずにシンプルにHashで設定することもできます。
proc
を使った動的な指定をしたい場合は、こちらを使うのがよいかもしれません。
ActiveAdmin::MenuTree.setup do |config|
config.menu_tree = [
{ id: "Dashboard", label: proc { I18n.t("active_admin.dashboard") } },
{
label: "Foo",
if: proc { "Something dynamic" }
children: [
{ id: "Bar" },
{ id: "Baz" }
]
}
]
end
Config gemを使っている場合は、to_hash
メソッドでHashにすることで使えます。
ActiveAdmin::MenuTree.setup do |config|
config.menu_tree = Settings.activeadmin.menu_tree.map(&:to_hash)
end
# config/settings.yml
activeadmin:
menu_tree:
# ...
Global gemなどでも同様にHashに変換すれば使えると思います。
フル設定例
yamlで使える全設定例は以下のような感じです。
activeadmin:
menu_tree:
# Specify the resource with `id`.
- id: Dashboard
- id: Product
# Specify a menu label with `label`.
- label: User Info
# Specify child elements with `children`.
children:
- id: User
- id: Profile
- label: Admin
children:
- id: AdminUser
label: Admin Users
# Comment resource will be handled specially.
- id: Comment
label: Admin Comments
- label: Others
children:
- id: Foo
- id: Bar
- label: Example Site
# You can pass the other options available for `menu` DSL, like `url`, `html_options`.
url: 'https://example.com'
html_options:
target: blank
# Nesting of children is also available.
- label: Lorem
children:
- label: ipsum
children:
- label: dolor
children:
- label: sit
children:
- label: amet
url: 'https://wikipedia.org/wiki/Lorem_ipsum'
html_options:
target: blank
-
id
- リソースIDを指定します(通常はモデル名) -
label
- ラベルを指定します -
children
- 子要素を配列で指定します -
Comment
リソースは通常リソースファイルがないですが、特別に処理されます -
url
,html_options
など、menu
メソッドで使えるオプションはそのまま渡せます- ※yamlなのでrubyの動的な指定はできません
こんな感じで、 ActiveAdmin::MenuTree を使えば ActiveAdmin のメニューをわかりやすく設定できます。
おまけ: gemの命名規則について
gemを作ったことのある方なら知っているかと思いますが、gemの名前を決める際の指針として、RubyGems公式のガイドラインがあります。
ざっくりポイントは以下の3点です。
・複数単語をくっつける場合はアンダースコア
・階層が分かれる場合はハイフン
・大文字や他の記号は使わない
そして、 ActiveAdmin と ActiveAdmin::MenuTree の命名は以下のようになっています。
GEM NAME | REQUIRE STATEMENT | MAIN CLASS |
---|---|---|
activeadmin |
require 'activeadmin' or require 'active_admin'
|
ActiveAdmin |
activeadmin-menu_tree |
require 'activeadmin/menu_tree' |
ActiveAdmin::MenuTree |
これを見ると、activeadmin
というgem名はガイドラインを守っていないことになりますね。
一応requireではactiveadmin
でもactive_admin
でもどちらでも読み込めるようになっています。ref.
ちなみに、ActiveAdminに限らずこのガイドラインを守っていない有名gemもそれなりにありますね。
(Rails関連のactivexxx
系やactionxxx
系を筆頭に)
ActiveAdmin::MenuTree では、activeadmin
の部分は本家と同じにし、menu_tree
の部分はガイドラインに従う形にしました。
今後gemを作る方の参考になれば。
おわりに
- ActiveAdminのメニュー設定を便利にする ActiveAdmin::MenuTree というgemのご紹介でした。ぜひみなさん使ってみてください!
- 不具合など見つけた方はissueなどで優しく教えてください
- プルリクエストも歓迎です