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

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

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

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

models/user.rb
accepts_nested_attributes_for が大事。

class User < ActiveRecord::Base
  has_many :phones
  accepts_nested_attributes_for :phones
end

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

def strong_params
  params.require(:user).permit(
    :name, :email,
    phones_attributes: [:number, :device],
  )
end

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

= 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をつくりたいんだって場合は、
コントロール側で

3.times do
  @user.phones.build
end

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

updateする時

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

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

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

def strong_params
  params.require(:user).permit(
    :name, :email,
    phones_attributes: [:id, :number, :device],
  )
end

  
よく忘れるなー。

何かありましたらコメントをどうぞ

comments powered by Disqus

人気の記事

950 Points チリ出身のギタリストが弾くドラゴンボールZがむちゃくちゃかっこいい…
774 Points Wordpress + Heroku + PostgreSQL + Amazon S3 = ¥0 / 無料でサイト運営
700 Points Rubyのチートシート 変数 / クラス / モジュール
524 Points Rubyのチートシート / アクティブサポート
451 Points 紙のデザイナーがウェブ開発できるようになるまでに必要なこと
435 Points Rails / Google Analyticsのデータを使って分析や管理画面のためのグラフをつくる
323 Points RailsとHerokuでノーティフィケーションをプッシュする / PusherとTurbolinksの兼ね合い
222 Points Rails / RSpec テスト書いたことない メンドクサイ(n´Д`)という時のチートシート
193 Points Rails / Ajaxを使って画面遷移しない一時保存機能をつける
193 Points Protractorでスクレイピングしてみた