今回も引き続きActiveAdminを触っていきます。
主に、Nested Resources を触ってゆきます。
それでは本編です。
目次
実行環境
- Rails 5.2.3
Nested Resources
Nested Resourcesは、ActiveAdmin で管理されるオブジェクトに関連づいたオブジェクトをフォームで編集するために使うようです。
書籍への著者、クラスへの人といった関係のものに使います。
1 対多 - has_many
書籍への口コミを設定します。(管理者の画面で設定するものではないという突っ込みはあるでしょうが。)
モデル定義
以下、コマンドでモデルを作成。
1 | rails generate model review score:integer comment::text book:references |
review モデルは作成されたものそのままでいいです。
1 | class Review < ApplicationRecord |
book モデルには、has_many: reviews
を追記します。
1 | class Book < ApplicationRecord |
ActiveAdmin 用設定
book モデルには、accepts_nested_attributes_for :reviews,allow_destroy: true
を追記します。
accepts_nested_attributes_for が無いと、(undefined method `new_record?' for nil:NilClass):
みたいなエラー表示が出ます。
1 | class Book < ApplicationRecord |
app/admin/books.rb には、以下を追記します。
1 | f.inputs do |
親のフォームが、review を複数持っていて、allow_destroy:true
を定義することで、削除用のチェックボックスが使用できます。
追記したものが以下の通りです。
1 | ActiveAdmin.register Book do |
以上を作成して、rails s
でサーバー起動して、表示を確認。
Review の項目が作成されて、「新規に Review を作成する」ボタンが作成されました。
「新規に Review を作成する」ボタンを押すと、Score と Comment が登録できます。
1 対多での関連付けられたフォームの作成ができました。
多対多 - has_and_belongs_to_many
今度は、多対多の関係にある例として、書籍に対しての著者を設定します。
モデル定義
以下、コマンドでモデルを作成。
1 | rails generate model author name:string |
以下の操作で中間テーブルを作成。
1 | rails generate migration create_authors_books author:references book:references |
中間テーブルの作成方法についてはRuby on Rails での多対多のアソシエーションの設定方法を参照。
review モデルには、has_and_belongs_to_many :books
を記述します。
空の名前を登録されたくないのでvalidates :name, presence: true
も追加します。
1 | class Author < ApplicationRecord |
book モデルには、has_and_belongs_to_many :authors
を追記します。
1 | class Book < ApplicationRecord |
ActiveAdmin 用設定
以下を実行して、ActiveAdmin の管理対象に author を追加。
1 | rails generate active_admin:resource author |
book モデルには、accepts_nested_attributes_for :authors,allow_destroy: true
を追記します。
1 | class Book < ApplicationRecord |
app/admin/books.rb には、以下を追記します。
1 | #permit_paramsに以下を追加 |
追記したものが以下の通りです。
1 | ActiveAdmin.register Book do |
以上を作成して、rails s
でサーバー起動して、表示を確認。
Author の項目が作成されて、Name を入力できるようになりました。
著者を自由に入力できるのは多対多のアソシエーションを生かせていない気がします。
用意した著者から選択する形を取りたかったのですが、has_and_belongs_to_many を使用した場合はできませんでした。
用意したリストから選択し、対象との関連付けを作成するので中間モデルにアクセスする必要があります。
しかし「has_and_belongs_to_many は中間モデルを持たないので、その用途では使えない」ということで納得しました。
この操作は、次の has_many through に任せることとします。
多対多 - has_many through
今度は、has_many through でアソシエーションを作って、ActiveAdmin で管理してみます。
多対多でアソシエーションするネタが枯渇してきましたが今度はお客さんを定義します。
お客さんのリストから選択して、関連付けできるようにします。
モデル定義
以下、コマンドでモデルを作成。
1 | rails generate model customer name:string |
以下の操作で中間モデルを作成。
客と書籍は購買(purchase)でつながることにします。
1 | rails generate model purchase customer:references book:references |
customer モデルには、アソシエーションのために以下を記述します。
1 | has_many :purchases |
空の名前を登録されたくないのでvalidates :name, presence: true
も追加します。
反映した customer モデルが以下の通りです。
1 | class Author < ApplicationRecord |
book モデルには、アソシエーションのために以下を記述します。
1 | has_many :purchases |
追記した book モデルが以下の通りです。
1 | class Book < ApplicationRecord |
Activeadmin 用設定
以下を実行して、ActiveAdmin の管理対象に customer を追加。
1 | rails generate active_admin:resource customer |
app/admin/customers.rb で、permit_params :name, :_destroy
を記述して入力パラメーターの許可を設定します。
1 | ActiveAdmin.register Customer do |
book モデルには、accepts_nested_attributes_for :purchases, allow_destroy: true
を追記します。
1 | class Book < ApplicationRecord |
accepts_nested_attributes_for の対象を中間モデルの purchases にするのがポイントです。
app/admin/books.rb には、以下を追記します。
1 | #permit_paramsに以下を追加 |
select の選択肢を author の name の一覧から作成します。
追記したものが以下の通りです。
1 | ActiveAdmin.register Book do |
以上を作成して、rails s
でサーバー起動して、表示を確認。
Author の項目が作成されて、Name を入力できるようになりました。
選択肢になるお客さんは、Customers の項目で作成しておきます。
作成しておくと、以下のように選ぶことができます。
今回は、ActiveAdmin で関連付けされたモデルの登録を作ってみました。
今回記事を書くに当たり、has_and_belongs_to_many と has_many through の中間テーブルの取り扱いの違いに気が付けず 4 日ほど悩んでしまいました。
似て非なる(詳しい人からすると似てないといわれるかもしれませんが)ものの区別は大事だと再認識しました。
ずいぶんかかりましたが、これで次から悩むことはなさそうです。
非 ActiveAdmin での Rails の学習にも、今回の経験が役に立つ気がします。
ではでは。