使用が想定される場面
- 例えばHomeモデルとStationモデルで1対多の関係の場合、Homeの作成時にStationもまとめてDB操作したい時。
- Homeをsaveしようとするタイミングで、Homeのバリデーションに加えてStationのバリデーションも自動で走り、問題なければ両方が作成させる処理をしたい時。
※子レコード(この場合はStation)のバリデーションやsaveとか考慮したくない時。
has_many、belongs_to、has_oneの関係で使用出来る。 - has_manyの場合で子レコードにあたる部分を複数まとめて登録したい時。
※controllerでbuildの部分を複数回実行して複数作成しておくと、フォームも自動的に複数個表示させる。
#Modelの定義
models/home.rb
has_many :stations, dependent: :destroy
accepts_nested_attributes_for :stations, allow_destroy: true
models/station.rb
belongs_to :home, optional: true
外部キーは、レコードに保存させる場合nilだと、バリデーションが発生してしまう。
つまりは、stationsテーブルは、homeのidが決定していないと正常に保存できない。
つまりは、homesレコードが保存された後でないといけない。
この状況を解消するため、 optional: trueを指定する。
#Controllerの定義
def new
@home = Home.new
# buildする際は、timesメソッドを使用することで、複数の子レコードをviewに渡すことが出来る。
2.times{@home.stations.build}
end
def create
if Home.create(home_params)
redirect_to root_path
else
render 'new'
end
end
private
def home_params
params.require(:home).permit(:name, :price, :address, :year, :content, stations_attributes: [:line, :station, :walk])
end
def set_params
@home = Home.find(params[:id])
end
def update_params
params.require(:home).permit(:name, :price, :address, :year, :content, stations_attributes:
[:line, :station, :walk, :_destroy, :id])
end
#viewの定義
new.html.erb
<%= form_for(@home) do |f| %> |
<div class="field"> |
<div>
<%= f.label :name, "物件名" %> |
</div>
# 省略
<% @home.stations.each_with_index do |station, index| %>
<%= f.fields_for :stations, station do |s_f| %>
<h2>最寄り駅<%= index + 1 %></h2>
<div class="field">
<div>
<%= s_f.label :line, "路線名" %>
</div>
<div>
<%= s_f.text_field :line %>
</div>
</div>
<div class="field">
<div>
<%= s_f.label :station, "駅名" %>
</div>
<div>
<%= s_f.text_field :station %>
</div>
</div>
<div class="field">
<div>
<%= s_f.label :walk, "徒歩分数" %>
</div>
<div>
<%= s_f.text_field :walk %>分
</div>
</div>
<% end %>
<% end %>
時折、fields_forで表示してもうまくフォームが表示されないときがあります。
その時はfields_forの第2引数のところに直接指定する。
※この例だと、station(@home.stationsに当たるもの)を指定する。
accepts_nested_attributes_forを使用せず、Form Objectを使用する場合
https://moneyforward.com/engineers_blog/2018/12/15/formobject/
https://qiita.com/9ro/items/10e3676741e09ffb98bb
- 参考URLはこちら