LoginSignup
3
5

More than 5 years have passed since last update.

Rails x Bootstrap4 x nested_attributesフォームのデザインパターン

Last updated at Posted at 2018-08-27
  • よく使うのでメモ書きに、最終的にこんな感じになります。

nested_pattern1.gif

インストール

  • nested_attributesのフォームを作る時にcocoonというGemを使うと便利なので、それを使います。
gem 'cocoon'
  • cocoonを使うためには、Gemのインストールと、assets/application.jsへの登録が必要です。
//= require cocoon
  • あとBootstrap4をRailsで使うので、あらかじめ設定しておいてください。(こちらの記事にわかりやすくまとめてありました。@NaokiIshimuraさんありがとうございます。)

モデルへの実装

  • 今回はわかりやすくUserDogを一対多で関連づけます。(nested_attributesを忘れない。)
  • またコードの簡略化のため、それぞれのモデルのパラメーターを配列にして定数化しておきます。
class User < ApplicationRecord
  ATTRIBUTES = %i[name].freeze

  has_many :dogs, dependent: :destroy, inverse_of: :user
  accepts_nested_attributes_for :dogs, allow_destroy: true, reject_if: :all_blank
end

class Dog < ApplicationRecord
  # nested_attributesの都合上、idと_destroyを加えている。
  ATTRIBUTES = %i[id _destroy name].freeze

  belongs_to :user
end

コントローラーへの実装

  • nested_attributesStrongParameterの対応を忘れない。
class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user
    else
      render :new
    end
  end

  private

  def user_params
    params
      .require(:user)
      .permit([*User::ATTRIBUTES, dogs_attributes: Dog::ATTRIBUTES])
  end
end

ビューの実装

  • ビューの構成は以下の通りです。(今回使う箇所だけ)
  • cocoonの仕様で、子要素のテンプレートになる_〇〇_fields.html.slimを作らないといけないことに注意してください。
  • cocoonのビュー周りの注意点は公式のリポジトリにまとめてあるので、気になった方は確認してください。
app/views/users/
├── _dog_fields.html.slim
├── new.html.slim
└── show.html.slim
  • 実際のコードは以下。
/ show.html.slim
p
  strong Name:
  = @user.name

ul
  - @user.dogs.each do |dog|
    li = dog.name

=> link_to 'Edit', edit_user_path(@user)
'|
=< link_to 'Back', users_path
/ new.html.slim
h2.py-3 New use
= form_for @user do |f|
  .form-group.row
    .col-md-3
      = f.label :name
    .col-md-9
      = f.text_field :name, class: 'form-control'
  .form-group.row
    .col-md-3
      = f.label :dogs
    .col-md-9.ml-auto
      #dogList
        = f.fields_for :dogs do |dog|
          = render 'dog_fields', f: dog
      = link_to_add_association f, :dogs, class: "btn btn-link", data: { association_insertion_node: "#dogList", association_insertion_method: "append" } do
        = fa_icon "plus", text: "アイテムを追加"
  = f.submit 'Submit', class: 'btn btn-success w-100'
/ _dog_fields.html.slim
.nested-fields.mb-3
  .form-row
    .col-md-10
      = f.text_field :name, placeholder: '名前', class: 'form-control'
    .col-md-2
      = link_to_remove_association "削除", f, class: "btn btn-danger"
  • cocoonの仕様上、nested-fieldsクラスを子要素につけないと追加されません
  • これにより、「追加ボタン」の位置を一番下にしたまま、新しいフォームが追加されます。

まとめ

  • こんな感じで作ればすんなりとnested_attributesのフォーム実装ができるかと思います!
3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5