76
72

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

accepts nested attributes for 実装まとめ

Last updated at Posted at 2017-11-04

#やろうとしていること 
多対多のテーブル構造を構築し、viewからparameterを送り、workとworkplaceに保存したい。
(placeのレコードはseedで作っているので、新規追加はしません。)
E-R図はこんな感じです。この会社が募集している仕事は、どの地域にあるのかをわかるようにしたい。

スクリーンショット 2017-10-21 23.29.14.gif

workテーブルとplaceテーブルの中間として、work_placeテーブルを作りました。

#コード
##モデル:


#work.rb
has_many :work_places, dependent: :destroy
has_many :places, :through => :work_places
accepts_nested_attributes_for :work_places, allow_destroy: true

#place.rb
has_many :work_places, dependent: :destroy
has_many :works, :through => :work_places

#work_place.rb
belongs_to :work
belongs_to :place

accepts_nested_attributes_forがキモ。上の例だと、workモデルに新しいレコードが保存された際に、そのwork_idとplace_idがwork_placeに保存されるようにする。中間テーブルを通りますよってことで、workモデルとplaceモデルに:throughを追加。

##コントローラー:

Works_Controller.rb
def new
   @work = Work.new
  @work.work_places.build
end

def create
 @work = Work.new(work_params)
 
end

def work_params
   params.require(:work).permit(:company)
end

ここではbuildが重要。workレコードが保存された際に、work_placeレコードにも保存をかけますよってことを指示する。

##ビュー:


<%= form_for @work do |f| %>
  <%= f.label :company, "会社名" %>
  <%= f.text_area :company %>
  <%= f.fields_for :work_places do |ff| %>
    <%= ff.label :placename, "渋谷" %>
    <%= ff.check_box :place_id,{}, 1,"渋谷",nil%>
    <%= ff.label :placename, "新宿" %>
    <%= ff.check_box :place_id,{}, 2,"新宿",nil %>
    <%= ff.label :placename, "池袋" %>
    <%= ff.check_box :place_id,{}, 3,"池袋",nil %>
  <%= f.submit "投稿" %>
<% end %>

#これでいけるかと思いきや。。。。(問題発生)
というわけでこれで保存できると思ったんですが、
work_placeモデルにplace_idが保存されない!
work_placeがunpermittedになっている。

スクリーンショット 2017-10-22 13.54.42.gif

insert work_placeは走って、work_idは保存されるのに〜!

#解決策はstrongparameterにありました!

なんと、accepts_nested_attributes_forを使うときは、strongparameterもいじらなければならないようです。

Works_Controller.rb
def new
   @work = Work.new
      @work.work_places.build
end

def create
 @work = Work.new(work_params)
 
end

def work_params
   params.require(:work).permit(:company, work_places_attributes:[:id,:place_id])
end

このように、関連させているモデル名(これはhasmanyしているのでsがついてwork_placesです)にattributesをつけて、カラムを追記してあげなければなりません。

すると。。。。

スクリーンショット 2017-11-04 16.13.32.gif

place_idも保存されました!

単に、モデルにaccepts_nested_attributes_forをつければいいのかと。。。。

#まとめると。。。。

モデル=>accepts_nested_attributes_forを入れましょう

コントローラー=>newメソッドの中にbuildを入れ、strongparameterにattributesをつけましょう(ここ大事!)

ビュー=>fields_forで関連付け

##個人開発をされている方へ

Moverというプロダクトを開発しています。登録していただくと、開発したプロダクトのテスト利用を依頼し、フィードバックをもらうことができます。自分のプロダクトを公開して個人開発を加速させましょう!! 現在僕のアカウントも登録されているので、そちらにテスト利用依頼をいただければ実際に使ってみた感想などをお送りさせて頂きます。(アドバイスなどではなく、一人のユーザーとしての感想となります。) もちろん無料です。
https://mover-web.herokuapp.com/

Screen Shot 2020-05-19 at 4.36.42 PM.gif

76
72
3

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
76
72

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?