LoginSignup
86
92

More than 5 years have passed since last update.

ネストされたモデル(親子関係を持つモデル)で、子を表示、編集するには

Last updated at Posted at 2014-05-10

概要

  • 親子関係を持つモデルで、親ビューから子を複数表示・編集方法。
  • 親子関係を持つモデルのStrongParameterの定義方法。

今後調査したい事

  • ビュー側で+ボタンを押す度に動的に子の入力画面を増やしたり、ーボタンで減らしたりする

モデル

accepts_nested_attributes_forを利用することで、newやcreateするときに子のデータもまとめて設定できるようになります。


# アンケート(親)
# アンケートは質問(子)を複数持つ
class Enquate < ActiveRecord::Base
# attributes :id, :title, 
  has_many :questions
  accepts_nested_attributes_for :questions
end

# 質問(子) 
class Question < ActiveRecord::Base
# attributes :id, :content
 belongs_to :enquate
end

コントローラ

has_manyでのオブジェクトの生成などはこちらも参考。
Railsドキュメント model
Railsガイド ActiveRecord Associations

StrongParameterにて、Enquateの内容に加えQuestionsの属性も許可するようにします。
ネストされたモデル(親子関係を持つモデル)でStrongParameterを利用する

class EnquatesController < ApplicationController

  def new
    @enquate = Enquate.new
    # 入力用に空のオブジェクトを1つ生成します。
    @enquate.questions.build
  end

  def create
    @enquate = Enquate.new(enquate_params)
    #... 
  end

  def enuqate_params
    params.require(:enquate).permit(:title, questions_attributes: [:id, :content])
  end
end

ビュー

form_for @enquate do |f| f.fields_for :questionsを利用します。

fields_forにaccepts_nested_fields_for指定のある属性名を指定すると、自動的に子分のフィールドを作成し、name属性をenquate[questions_attribute[0]][content]のように展開してくれます。

= form_for @enquate do |f|
  .field
    = f.label :title
    = f.text_field :title
  .questions
    = f.fields_for :questions do |q|
      .field
       # 例 <input id="enquate_questions_attributes_0_enquate_id" name="enquate[questions_attributes][0][enquate_id]" type="hidden" value="2" />
       = q.hidden_field :enquate_id
      .field
       = q.label :content
       # 例 <input id="enquate_questions_attributes_0_content" name="enquate[questions_attributes][0][content]" type="text" value="Test" />
       = q.text_field:

子要素のキーが複合キーの場合

※ もし子要素の主キーが複合キーで、composite_primary_keysを利用している場合、:idではなく、:a_id, :b_idなど複合キーを明示しないと動作しないっぽい。(gemをいじったりする必要がでてしまう??)

= q.hidden_field :id # 値は"[1070, 190]"のように複合キーの配列の文字列になるけど、composite_primary_keys内で"[1070,190]"と比較されてたりして、うまく動作しない。
= q.hidden_field :a_id
= q.hidden_field :b_id

fields_forの参照元オブジェクトにアクセスするには

object属性を利用する.

= f.fields_for :questions do |q|
  = q.object.id

fields_forの参照元オブジェクト(has_many時)のインデックスを取得するには

indexを利用する

= f.fields_for :questions do |q|
  = q.object.id
  = q.index

余談

  • javascriptで、動的にQuestionの入力フィールドを増やしたい場合、HTMLのidやnameを知らずにrailsオブジェクトで行えるgemやメソッドってあるの?
  • StrongParameter、ネストされたモデルの使い方、親子間のビューの使い方をざーっと眺めて、なんとなくRailsが使えるようになってきた気がする。
86
92
1

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
86
92