質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

解決済

1回答

2140閲覧

accepts_nested_attributes_forを利用したform(check_box)のEdit画面でチェックが消えてしまう

Yuinyan

総合スコア312

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

0グッド

2クリップ

投稿2016/10/14 05:10

編集2016/10/14 10:44

###前提・実現したいこと

accepts_nested_attributes_forでネストされたフォームからデータを入力できるのですが、エディット画面では、checkboxの情報を取得できません。

入力された値を正しくEditでも表示され、その後もUpdate処理できるようにしたいです。

###発生している問題・エラーメッセージ

https://teratail.com/questions/14954

ここで書かれているような実装をしているのですが、私の場合は、cocoonというgemを使っており、ネストされたオブジェクトの特定が上手くいっていません。

###該当のソースコード

ruby

1event.rb 2 3has_many :tickets 4accepts_nested_attributes_for :tickets, allow_destroy: true

ruby

1ticket.rb 2belongs_to :event

ruby

1form 2 3<% 4if @event.id.nil? 5 resource_info = [@group, @event] 6else 7 resource_info = [@event] 8end 9%> 10 11<%= form_for( resource_info,:html => {:multipart => true, :class => "form-horizontal h-adr"}) do |f| %> 12 13<div class="row "> 14 <div class="col-md-3" > 15 <div class="gray"><span class="label-title">タイトル</span></div> 16 </div> 17 <div class="col-md-9"> 18 <%= f.text_field :title, :class =>"form-control" %> 19 </div> 20</div> 21 22<div class="row "> 23 <div class="col-md-3" > 24 <div class="gray"><span class="label-title">サブタイトル</span></div> 25 </div> 26 <div class="col-md-9"> 27 <%= f.text_field :subtitle, :class =>"form-control" %> 28 </div> 29</div> 30 31<div class="row "> 32 <div class="col-md-3" > 33 <div class="gray"><span class="label-title">概要</span></div> 34 </div> 35 <div class="col-md-9"> 36 37 38 <%= f.text_area :description, rows:15,:id => "event_description" ,:class =>"form-control" %> 39 </div> 40</div> 41 42<div class="row "> 43 <div class="col-md-3" > 44 <div class="gray"><span class="label-title">場所</span></div> 45 </div> 46 <div class="col-md-9" > 47 <div class="row"> 48 <div class="col-md-3"> 49 <%= f.label :zipcode,"郵便番号"%> 50 <%= f.text_field :zipcode ,:placeholder =>"郵便番号", :id => "event_zipcode", :class =>"form-control p-postal-code" %> 51 </div> 52 </div> 53 <%= f.label :address,"住所"%> 54 <div class="row"> 55 <div class="col-md-3"> 56 <%= f.text_field :pref ,:placeholder =>"都道府県 ", :class =>"form-control p-region" %> 57 </div> 58 <div class="col-md-3"> 59 60 <%= f.text_field :city ,:placeholder =>"市区 ", :id => "address_city", :class =>"form-control p-locality" %> 61 </div> 62 <div class="col-md-6"> 63 <%= f.text_field :address02,:placeholder =>"住所 ",:id => "address_street",:class =>"p-street-address p-extended-address form-control" %> 64 65 66 </div> 67 </div> 68 69 </div> 70</div> 71 72<div class="row "> 73 <div class="col-md-12"> 74 75 <div id="tickets"> 76 <%= f.fields_for :tickets do |builder| %> 77 <%= render "ticket_fields", f: builder %> 78 <% end %> 79 <div class="links text-center"> 80 <%= link_to_add_association "追加",f, :tickets, :class => "btn btn-info btn-lg" %> 81 </div> 82 83 </div> 84 </div> 85</div> 86 87<div class="col-md-4 col-md-offset-4 mt20"> 88 89<%= f.submit "保存" ,:id =>"eventsubmit" ,:class => "btn btn-lg btn-success btn-block" ,:disabled => "disabled" %> 90</div> 91<% end %> 92</div> 93

ruby

1ticket_fields.html.erb 2cocoonのpartialの部分です。 3 4<div class="nested-fields"> 5<h3>tickets</h3> 6 7 8<div class="row text-center"> 9 <div class="col-md-3"> 10 <span class="label-title">title</span> 11 </div> 12 <div class="col-md-9"> 13 <div class='input-group'> 14 <%= f.text_field :title, :class => "form-control" % 15 </div> 16 </div> 17</div> 18 19 20<div class="row text-center"> 21 <div class="col-md-3"> 22 <span class="label-title">対象者</span> 23 </div> 24 25 <div class="col-md-9"> 26 <%= f.hidden_field :id %> 27 28<% students = { '小学生' => 1, '中学生' => 2, '高校生' => 3 } %> 29 30<% students.each do |st,i| %> 31 <%= f.check_box :student_type, { multiple: true , include_hidden: false }, i %> 32 <%= f.label :student_type, st, :value => i %> 33<% end %> 34 35 </div> 36</div> 37 38 39<%= link_to_remove_association 'remove this', f %> 40</div>

上記のようなフォームから、下記のようにDBに格納されたことは確認できました。
student_type: "["1", "2"]"

これをeditで確認すると、このままでは、checked: の規定がないため、何も表示されません。

###試したこと

https://teratail.com/questions/14954

を確認し、checked: を実装しようとしたのですが、Ticketからfindすることが出来ていません。

パラメータを確認すると、

Parameters: {"utf8"=>"✓", "authenticity_token"=>" 省略 , "tickets_attributes"=>{"0"=>{"id"=>"24", "_destroy"=>"false"}}, ""}, "button"=>"", "id"=>"23"}

上記の通りだったので、Ticket.find(params[:tickets_attributes[:id]] を試したのですが、うまく取得できませんでした。

どのようにすればcheckedの判定ができますでしょうか。

教えてください

###補足情報(言語/FW/ツール等のバージョンなど)

Ruby 2.3
rails 4.2.1
cocoon 1.2.9

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hana-da

2016/10/14 10:05

ticket_fields.html.erb の form_for の部分を公開してください
Yuinyan

2016/10/14 10:22

ご連絡有難うございます。form_forの部分を記載しました。不足がありましたらご連絡下さい。
hana-da

2016/10/14 10:24

あ、すみません。form_forで囲まれている部分全体です。他にもevent.rb や ticket.rb その他関連するコントローラなども開示すると解決が早いと思います。その際、みやすいように ``` を分けてもらえるとさらによいです。
Yuinyan

2016/10/14 10:27

すみません、少々お待ちください。
guest

回答1

0

ベストアンサー

上記のようなフォームから、下記のようにDBに格納されたことは確認できました。
student_type: "["1", "2"]"

ここがとても気になります。
テーブル(モデル)設計を間違えていませんか?

記載されている情報から判断すると

  • Eventは複数のTicketを持つ事ができて、Ticketには複数のstudent_typeを指定できる。
  • student_typeは複数のTicketから指定される事がある

という事になるので

ruby

1class Event 2 has_many :tickets 3end 4 5class Ticket 6 belongs_to :event 7 has_many :ticket_student_types 8end 9 10class TicketStudentType 11 belongs_to :ticket 12 belongs_to :student_type 13end 14 15class StudentType 16 has_many :tickets 17end

になると思うのですが。。。いかがでしょう?


今は恐らくticketsテーブルのstudent_typeカラム(属性)がstring(文字列)で定義されているので折角formで複数指定できるcheckboxをつくってsubmitしても

  • paramsに入るところまではちゃんと ["1", "2"] という形で配列に入っているのに
  • Ticket の student_type に入ると to_s されて "["1", "2"]" という形の文字列になってしまっています

という事で f.checkbox のことろで event.ticketsstudent_type を参照した際 "1""2" といった文字列が出てくれば簡単に比較して checked をつける事ができますが、**"["1", "2"]"**という誤った形式の文字列で保存されているため容易には比較できず checked をつける事も非常に難しいです。

これを無理矢理配列に戻したりしてcheckedをつける方法はありますが、間違いを正す方が今後のためですし、正さないとstudent_typeについてrailsの便利機能(小学生対象のTicketをまとめて取得するなど)も使えなくなるのでここには書きません。

まずはテーブル(モデル)を正しい形に直しましょう。
そうすれば、それほど悩まずともできるはずです。
やり方がわからない、うまくいかないのはテーブル(モデル)の設計が間違えているからです。


Parameters: {"utf8"=>"✓", "authenticity_token"=>" 省略 , "tickets_attributes"=>{"0"=>{"id"=>"24", "_destroy"=>"false"}}, ""}, "button"=>"", "id"=>"23"}

上記の通りだったので、Ticket.find(params[:tickets_attributes[:id]] を試したのですが、うまく取得できませんでした。

これは色々おかしいところが多いです。

  • find() の ( に対応する ) がない
  • Symbol である :tickets_attributes に [:id] がついている

のでエラーになります。

Ticket.find(params[:tickets_attributes][:id]) と書けば文法上は大丈夫ですが
params[:tickets_attributes]{"0"=>{"id"=>"24", "_destroy"=>"false"}}, ""} という Hash なので :tickets_attributes の直下に :id はなく nil が返ります。

"24" がほしいのであれば params[:tickets_attributes][0][:id] で取得する必要があります。

投稿2016/10/14 14:31

hana-da

総合スコア1728

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Yuinyan

2016/10/15 02:54

有難うございます。後程時間をかけて確認させて頂きます。 ちなみに下記をつけることで何とかやりたいことはできることができました。(おっしゃられる通り後々他の部分で影響がでるかもしれないので、モデルの部分はいずれにせよ見直しを考えてみます。) <% checked = f.object.payment_type.presence || [] %> また単純に一つのカラムに[]を指定して入れているのですが、これがあまりよくないのでしょうか。 ここのカラムは確かに string でしたのでここが問題になるのでしょうか。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問