Rails いつも忘れる集 / アソシエーションのあるモデルを含んだフォーム作成

Shunsuke Sawada

いっつも何かつくる時にググっているもの。
いいかげん記憶したいけど、いつも忘れる…。

関係モデルを含むフォームの作成

has_many や has_one などでアソシエーションがあるモデルを含むフォームを作成したい時。

models/user.rb
accepts_nested_attributes_for が大事。

ruby
1
2
3
4
class User < ActiveRecord::Base
  has_many :phones
  accepts_nested_attributes_for :phones
end

  
controllers/user_controller.rb
phones_attributes が必須。ないと値が取れない。

ruby
1
2
3
4
5
6
def strong_params
  params.require(:user).permit(
    :name, :email,
    phones_attributes: [:number, :device],
  )
end

  
views/users/new.html.haml
fields_for でネストされたモデルのフォームをつくる。

haml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
= form_for @user do |f|

  = f.label :name
  = f.text_field :name

  = f.label :email
  = f.text_field :email

  = f.fields_for :phones, @user.phones.build do |p|
    = p.label :number
    = p.text_field :number

    = p.label :device
    = p.text_field :device, options_for_select(["携帯", "自宅"]), prompt: ""

@user.phones.build を直接ビューの中に書いてもいいんだけど、
バリデーションエラーで render 'new' すると入力した値が消えるので、
コントロール側で @job.type_connections.build とした方が良いと思う。
  
もし、has_many ではなく has_one のアソシエーションを使っている場合は、
@user.phones.build ではなく @user_build_phone なので注意。

has_many で3個同時にphoneをつくりたいんだって場合は、
コントロール側で

ruby
1
2
3
3.times do
  @user.phones.build
end

とすると、自動的に3つ分フィールドが現れる。

updateする時

これで一見、いい感じになったと思いきや、
updateメソッドを実装する時にもちょっとハマる。

何も考えずにやると has_many で関連付けられたデータが沢山できてしまう。
ので、該当するidをコントローラーに渡す必要がある。

controllers/users_controller.rb
:id を許可しておくのを意外と忘れがち。

ruby
1
2
3
4
5
6
def strong_params
  params.require(:user).permit(
    :name, :email,
    phones_attributes: [:id, :number, :device],
  )
end

  
よく忘れるなー。

2
Shunsuke Sawada

おすすめの記事

CakePHPのセレクトメニューでよく使う配列
5
Rails よく忘れる集 / バリデーションエラーでレイアウトが崩れるのを防ぐ
1
Rails よく忘れる集 / アソシエーションが深いN+1問題