Problem z has_many :through oraz fields_for

Witam,

mam ponizsza relacje miedzy modelami:

Report:
has_many :report_options
accepts_nested_attributes_for :report_options

ReportOption:
belongs_to :report
belongs_to :workbook
belongs_to :view

View:
has_many :report_options
has_many :reports, :through => :report_options

Workbook:
has_many :report_options
has_many :reports, :through => :report_options

Tabela report_options ma kolumny:

report_id
workbook_id
view_id
pdf: boolean
xls: boolean
png: boolean

Probuje utworzyc formularz ktory pozwoli mi na zapisywanie danych do tabeli report_options. W widoku formularza uzytkownik bedzie mial do wyboru dla kazdego dostepnego view oraz dostepnego workbook wybrac odpowiednie formaty za pomoca checkboxow:

               PDF XLS PNG

view_1
workbook_1
view_2
workbook_2
view_3
workbook_3

Chcialbym teraz zapisac tego typu wartosci do tabeli report_options, jesli np uzytkownik wybral workbook_3 (PDF i XLS) oraz view_1 (PNG)

Jak najlepiej podejsc do takiego problemu?

Utworzylem helper ktory buduje mi hierarchie workboo oraz view z checkboxami PDF, XLS, PNG:

def dashboard_table(report_option, user_id)
    @level_1 = 1
    @level_2 = 0
    @level_3 = 0
    @level_4 = 0
    accounts = Account.where(user_id: user_id)
    concat(content_tag(:div, class: "table-responsive", 
                    style: "overflow: hidden; outline: none;", 
                    tabindex: "4") do
      concat(content_tag(:table, class: "table table-hover tree") do
        concat(content_tag(:thead) do
          concat(content_tag(:tr) do
            concat(content_tag(:th))
            %w(PDF XLS PNG TWB Open).each do |format|
              concat(content_tag(:th) do
                format
              end)
            end
          end)
        end)
        concat(content_tag(:tbody) do
          accounts.each do |account|
            concat(content_tag(:tr, class: "treegrid-#{@level_1}") do
              concat(content_tag(:td) do
                account.name
              end)
              5.times do
                concat(content_tag(:td))
              end
            end)
            sites = Site.where(account_id: account.id)
            @level_2 = @level_1 + 1
            if sites.count >= 1
              sites.each do |site|
                concat(content_tag(:tr, class: "treegrid-#{@level_2} treegrid-parent-#{@level_1}") do
                  concat(content_tag(:td) do
                    site.site_name
                  end)
                  5.times do
                    concat(content_tag(:td))
                  end
                end)
                workbooks = Workbook.where(site_id: site.id)
                @level_3 = @level_2 + 1
                if workbooks.count >= 1
                  workbooks.each do |workbook|
                    concat(content_tag(:tr, class: "treegrid-#{@level_3} treegrid-parent-#{@level_2}") do
                      concat(content_tag(:td) do
                        workbook.workbook_name
                      end)
                      concat(content_tag(:td) do
                        concat(content_tag(:div, class: "checkbox m-0") do
                          concat(content_tag(:label) do
                            concat(report_option.check_box :pdf, {}, true, false)
                            concat(content_tag(:i,  class: "input-helper") do
                            end)
                          end)
                        end)
                      end)
                      concat(content_tag(:td) do
                        concat(content_tag(:div, class: "checkbox m-0") do
                          concat(content_tag(:label) do
                            concat(report_option.check_box :xls, {}, true, false)
                            concat(content_tag(:i,  class: "input-helper") do
                            end)
                          end)
                        end)
                      end)
                      concat(content_tag(:td) do
                        concat(content_tag(:div, class: "checkbox m-0") do
                          concat(content_tag(:label) do
                            concat(report_option.check_box :png, {}, true, false)
                            concat(content_tag(:i,  class: "input-helper") do
                            end)
                          end)
                        end)
                      end)
                      concat(content_tag(:td) do
                        concat(content_tag(:div, class: "checkbox m-0") do
                          concat(content_tag(:label) do
                            concat(report_option.check_box :twb, {}, true, false)
                            concat(content_tag(:i,  class: "input-helper") do
                            end)
                          end)
                        end)
                      end)
                    end)
                    views = View.where(workbook_id: workbook.id)
                    @level_4 = @level_3 + 1
                    if views.count >= 1
                      views.each do |view|
                        concat(content_tag(:tr, class: "treegrid-#{@level_4} treegrid-parent-#{@level_3}") do
                          concat(content_tag(:td) do
                            view.view_name
                          end)
                          concat(content_tag(:td) do
                            concat(content_tag(:div, class: "checkbox m-0") do
                              concat(content_tag(:label) do
                                concat(report_option.check_box :pdf, {}, true, false)
                                concat(content_tag(:i,  class: "input-helper") do
                                end)
                              end)
                            end)
                          end)
                          concat(content_tag(:td) do
                            concat(content_tag(:div, class: "checkbox m-0") do
                              concat(content_tag(:label) do
                                concat(report_option.check_box :xls, {}, true, false)
                                concat(content_tag(:i,  class: "input-helper") do
                                end)
                              end)
                            end)
                          end)
                          concat(content_tag(:td) do
                            concat(content_tag(:div, class: "checkbox m-0") do
                              concat(content_tag(:label) do
                                concat(report_option.check_box :png, {}, true, false)
                                concat(content_tag(:i,  class: "input-helper") do
                                end)
                              end)
                            end)
                          end)
                          concat(content_tag(:td) do
                            concat(content_tag(:div, class: "checkbox m-0") do
                              concat(content_tag(:label) do
                                concat(report_option.check_box :twb, {}, true, false)
                                concat(content_tag(:i,  class: "input-helper") do
                                end)
                              end)
                            end)
                          end)
                       end)
                      end
                    end
                    @level_3 = @level_4 + 1
                  end
                end
                @level_2 = @level_4 + 1
              end
            end
            @level_1 = @level_4 + 1
          end
        end)
      end)
    end)
  end

W formularzu Report _form.html.erb:

<%= f.fields_for :report_options do |report_option| %>
<% dashboard_table(report_option, current_user) %>
<% end %>

Niestety przy takim podejsciu zapisuje sie tylko jeden rekord do tabeli report_options bez informacji o kluczu view lub workbook. Znowu gdy w metodzie helpera przy listowaniu view lub workbook umieszczam fields_for tworza sie dla kazdego workbook lub view z osobna co powoduje zapisywanie do tabeli report_options zbednych pustych rekordow. Czy spotkal sie ktos z podobnym problemem?

Zmienilem troszke podejscie a mianowicie usunalem model ReportOption i zastapilem go dwoma modelami ReportWorkbook oraz ReportView:

Report:
  has_many :report_workbooks
  has_many :report_views
  has_many :workbooks, :through => :report_workbooks
  has_many :views, :through => :report_views
  accepts_nested_attributes_for :report_workbooks
  accepts_nested_attributes_for :report_views

View:
  belongs_to :workbook
  has_many :report_views
  has_many :reports, :through => :report_views

Workbook:
 has_many :views, dependent: :destroy
  has_many :report_workbooks
  has_many :reports, :through => :report_workbooks

ReportWorkbook:
  belongs_to :tableau_report

ReportView:
  belongs_to :tableau_report

Helper:

module ReportsHelper
  def dashboard_table(report, user_id)
    @level_1 = 1
    @level_2 = 0
    @level_3 = 0
    @level_4 = 0
    accounts = Account.where(user_id: user_id)
    concat(content_tag(:div, class: "table-responsive", 
                    style: "overflow: hidden; outline: none;", 
                    tabindex: "4") do
      concat(content_tag(:table, class: "table table-hover tree") do
        concat(content_tag(:thead) do
          concat(content_tag(:tr) do
            concat(content_tag(:th))
            %w(PDF XLS PNG TWB Open).each do |format|
              concat(content_tag(:th) do
                format
              end)
            end
          end)
        end)
        concat(content_tag(:tbody) do
          accounts.each do |account|
            concat(content_tag(:tr, class: "treegrid-#{@level_1}") do
              concat(content_tag(:td) do
                account.name
              end)
              5.times do
                concat(content_tag(:td))
              end
            end)
            sites = Site.where(account_id: account.id)
            @level_2 = @level_1 + 1
            if sites.count >= 1
              sites.each do |site|
                concat(content_tag(:tr, class: "treegrid-#{@level_2} treegrid-parent-#{@level_1}") do
                  concat(content_tag(:td) do
                    site.site_name
                  end)
                  5.times do
                    concat(content_tag(:td))
                  end
                end)
                workbooks = Workbook.where(site_id: site.id)
                @level_3 = @level_2 + 1
                if workbooks.count >= 1
                  workbooks.each do |workbook|
                    concat(content_tag(:tr, class: "treegrid-#{@level_3} treegrid-parent-#{@level_2}") do
                      report.fields_for :report_workbooks do |trw|
                      concat(content_tag(:td) do
                        workbook.workbook_name
                      end) 
                      concat(content_tag(:td) do
                        concat(content_tag(:div, class: "checkbox m-0") do
                          concat(content_tag(:label) do
                            concat(trw.check_box :pdf, {}, true, false)
                            concat(content_tag(:i,  class: "input-helper") do
                            end)
                          end)
                        end)
                      end)
                      concat(content_tag(:td) do
                        concat(content_tag(:div, class: "checkbox m-0") do
                          concat(content_tag(:label) do
                            concat(trw.check_box :xls, {}, true, false)
                            concat(content_tag(:i,  class: "input-helper") do
                            end)
                          end)
                        end)
                      end)
                      concat(content_tag(:td) do
                        concat(content_tag(:div, class: "checkbox m-0") do
                          concat(content_tag(:label) do
                            concat(trw.check_box :png, {}, true, false)
                            concat(content_tag(:i,  class: "input-helper") do
                            end)
                          end)
                        end)
                      end)
                      concat(content_tag(:td) do
                        concat(content_tag(:div, class: "checkbox m-0") do
                          concat(content_tag(:label) do
                            concat(trw.check_box :twb, {}, true, false)
                            concat(content_tag(:i,  class: "input-helper") do
                            end)
                          end)
                        end)
                      end)
                      end
                    end)
                    views = View.where(workbook_id: workbook.id)
                    @level_4 = @level_3 + 1
                    if views.count >= 1
                      views.each do |view|
                        concat(content_tag(:tr, class: "treegrid-#{@level_4} treegrid-parent-#{@level_3}") do
                          report.fields_for :report_views do |trv|
                          concat(content_tag(:td) do
                            view.view_name
                          end)
                          concat(content_tag(:td) do
                            concat(content_tag(:div, class: "checkbox m-0") do
                              concat(content_tag(:label) do
                                concat(trv.check_box :pdf, {}, true, false)
                                concat(content_tag(:i,  class: "input-helper") do
                                end)
                              end)
                            end)
                          end)
                          concat(content_tag(:td) do
                            concat(content_tag(:div, class: "checkbox m-0") do
                              concat(content_tag(:label) do
                                concat(trv.check_box :xls, {}, true, false)
                                concat(content_tag(:i,  class: "input-helper") do
                                end)
                              end)
                            end)
                          end)
                          concat(content_tag(:td) do
                            concat(content_tag(:div, class: "checkbox m-0") do
                              concat(content_tag(:label) do
                                concat(trv.check_box :png, {}, true, false)
                                concat(content_tag(:i,  class: "input-helper") do
                                end)
                              end)
                            end)
                          end)
                          concat(content_tag(:td) do
                            concat(content_tag(:div, class: "checkbox m-0") do
                              concat(content_tag(:label) do
                                concat(trv.check_box :twb, {}, true, false)
                                concat(content_tag(:i,  class: "input-helper") do
                                end)
                              end)
                            end)
                          end)
                          end
                       end)
                      end
                    end
                    @level_3 = @level_4 + 1
                  end
                end
                @level_2 = @level_4 + 1
              end
            end
            @level_1 = @level_4 + 1
          end
        end)
      end)
    end)
  end
end

W tym momencie tworzone sa rekordy w tabelach report_views oraz report_workbooks odpowiednio z opcjami pdf, xls, png, tbw. Niestety nie sa zapisywane rekordy dla klucza report_workbook_id w tabeli report_workbooks oraz dla klucza report_view_id w tabeli report_views.

Dodajac hidden_field zapisywane sa wszystkie rekordy anwet te w ktorych nie zostala wybrana zadna z opcji pdf, xls, png czy tbw.

Niestety brakuje mi pomyslu jak dodac wartosci report_workbook_id oraz report_view_id.

Params wyglada nastepujaco:

“report_workbooks_attributes”=>{“0”=>{“pdf”=>“true”, “xls”=>“true”}, “1”=>{“pdf”=>“true”, “xls”=>“true”, “png”=>“true”}, “2”=>{“xls”=>“true”}, “7”=>{“pdf”=>“true”, “xls”=>“true”}, “9”=>{“pdf”=>“true”}}, “report_views_attributes”=>{“5”=>{“pdf”=>“true”, “xls”=>“true”}, “6”=>{“xls”=>“true”, “png”=>“true”}, “15”=>{“pdf”=>“true”, “xls”=>“true”}},

Gdy dodam w helperze:

report.fields_for :report_workbooks do |trw|
trw.hidden_field :report_workbook_id, value: workbook.id

oraz
report.fields_for :report_views do |trv|
trv.hidden_field :report_view_id, value: view.id

Params hash zawiera wszystkie wartosci i zapisuje do bazy:

“report_workbooks_attributes”=>{“0”=>{“workbook_id”=>“556”, “pdf”=>“true”}, “1”=>{“workbook_id”=>“558”, “pdf”=>“true”}, “2”=>{“workbook_id”=>“560”, “pdf”=>“true”, “xls”=>“true”}, “3”=>{“workbook_id”=>“561”}, “4”=>{“workbook_id”=>“562”}, “5”=>{“workbook_id”=>“563”}, “6”=>{“workbook_id”=>“564”, “pdf”=>“true”}, “7”=>{“workbook_id”=>“565”}, “8”=>{“workbook_id”=>“566”, “xls”=>“true”, “png”=>“true”, “twb”=>“true”}, “9”=>{“workbook_id”=>“567”}, “10”=>{“workbook_id”=>“568”}, “11”=>{“workbook_id”=>“569”}, “12”=>{“workbook_id”=>“570”}, “13”=>{“workbook_id”=>“571”}, “14”=>{“workbook_id”=>“572”}, “15”=>{“workbook_id”=>“573”}, “16”=>{“workbook_id”=>“574”}, “17”=>{“workbook_id”=>“575”}, “18”=>{“workbook_id”=>“576”}, “19”=>{“workbook_id”=>“577”}, “20”=>{“workbook_id”=>“578”}, “21”=>{“workbook_id”=>“579”}, “22”=>{“workbook_id”=>“580”}, “23”=>{“workbook_id”=>“581”}, “24”=>{“workbook_id”=>“582”}, “25”=>{“workbook_id”=>“583”}, “26”=>{“workbook_id”=>“584”}, “27”=>{“workbook_id”=>“585”}, “28”=>{“workbook_id”=>“586”}, “29”=>{“workbook_id”=>“587”}, “30”=>{“workbook_id”=>“588”}, “31”=>{“workbook_id”=>“589”}, “32”=>{“workbook_id”=>“590”}, “33”=>{“workbook_id”=>“591”}, “34”=>{“workbook_id”=>“592”}, “35”=>{“workbook_id”=>“593”}, “36”=>{“workbook_id”=>“594”}, “37”=>{“workbook_id”=>“595”}, “38”=>{“workbook_id”=>“596”}, “39”=>{“workbook_id”=>“597”}, “40”=>{“workbook_id”=>“598”}, “41”=>{“workbook_id”=>“599”}, “42”=>{“workbook_id”=>“600”}, “43”=>{“workbook_id”=>“601”}, “44”=>{“workbook_id”=>“554”}, “45”=>{“workbook_id”=>“557”}, “46”=>{“workbook_id”=>“559”}, “47”=>{“workbook_id”=>“555”}}, “report_views_attributes”=>{“0”=>{“view_id”=>“1082”}, “1”=>{“view_id”=>“1084”, “xls”=>“true”}, “2”=>{“view_id”=>“1087”, “pdf”=>“true”, “png”=>“true”}, “3”=>{“view_id”=>“1086”}, “4”=>{“view_id”=>“1088”}, “5”=>{“view_id”=>“1089”}, “6”=>{“view_id”=>“1091”}, “7”=>{“view_id”=>“1090”, “pdf”=>“true”}, “8”=>{“view_id”=>“1093”, “pdf”=>“true”, “xls”=>“true”}, “9”=>{“view_id”=>“1095”, “pdf”=>“true”}, “10”=>{“view_id”=>“1098”, “pdf”=>“true”}, “11”=>{“view_id”=>“1092”}, “12”=>{“view_id”=>“1094”}, “13”=>{“view_id”=>“1096”}, “14”=>{“view_id”=>“1099”}, “15”=>{“view_id”=>“1097”}, “16”=>{“view_id”=>“1100”}, “17”=>{“view_id”=>“1101”}, “18”=>{“view_id”=>“1103”}, “19”=>{“view_id”=>“1102”}, “20”=>{“view_id”=>“1104”}, “21”=>{“view_id”=>“1105”}, “22”=>{“view_id”=>“1106”}, “23”=>{“view_id”=>“1109”}, “24”=>{“view_id”=>“1111”}, “25”=>{“view_id”=>“1113”}, “26”=>{“view_id”=>“1107”}, “27”=>{“view_id”=>“1108”}, “28”=>{“view_id”=>“1110”}, “29”=>{“view_id”=>“1112”}, “30”=>{“view_id”=>“1115”}, “31”=>{“view_id”=>“1114”}, “32”=>{“view_id”=>“1116”}, “33”=>{“view_id”=>“1117”}, “34”=>{“view_id”=>“1118”}, “35”=>{“view_id”=>“1119”}, “36”=>{“view_id”=>“1121”}, “37”=>{“view_id”=>“1120”}, “38”=>{“view_id”=>“1122”}, “39”=>{“view_id”=>“1124”}, “40”=>{“view_id”=>“1123”}, “41”=>{“view_id”=>“1125”}, “42”=>{“view_id”=>“1127”}, “43”=>{“view_id”=>“1130”}, “44”=>{“view_id”=>“1133”}, “45”=>{“view_id”=>“1135”}, “46”=>{“view_id”=>“1126”}, “47”=>{“view_id”=>“1129”}, “48”=>{“view_id”=>“1128”}, “49”=>{“view_id”=>“1131”}, “50”=>{“view_id”=>“1132”}, “51”=>{“view_id”=>“1134”}, “52”=>{“view_id”=>“1136”}, “53”=>{“view_id”=>“1139”}, “54”=>{“view_id”=>“1137”}, “55”=>{“view_id”=>“1138”}, “56”=>{“view_id”=>“1140”}, “57”=>{“view_id”=>“1142”}, “58”=>{“view_id”=>“1141”}, “59”=>{“view_id”=>“1143”}, “60”=>{“view_id”=>“1144”}, “61”=>{“view_id”=>“1146”}, “62”=>{“view_id”=>“1145”}, “63”=>{“view_id”=>“1147”}, “64”=>{“view_id”=>“1148”}, “65”=>{“view_id”=>“1150”}, “66”=>{“view_id”=>“1154”}, “67”=>{“view_id”=>“1157”}, “68”=>{“view_id”=>“1160”}, “69”=>{“view_id”=>“1163”}, “70”=>{“view_id”=>“1149”}, “71”=>{“view_id”=>“1151”}, “72”=>{“view_id”=>“1152”}, “73”=>{“view_id”=>“1155”}, “74”=>{“view_id”=>“1153”}, “75”=>{“view_id”=>“1158”}, “76”=>{“view_id”=>“1159”}, “77”=>{“view_id”=>“1156”}, “78”=>{“view_id”=>“1161”}, “79”=>{“view_id”=>“1164”}, “80”=>{“view_id”=>“1167”}, “81”=>{“view_id”=>“1170”}, “82”=>{“view_id”=>“1173”}, “83”=>{“view_id”=>“1162”}, “84”=>{“view_id”=>“1165”}, “85”=>{“view_id”=>“1168”}, “86”=>{“view_id”=>“1166”}, “87”=>{“view_id”=>“1169”}, “88”=>{“view_id”=>“1171”}, “89”=>{“view_id”=>“1172”}, “90”=>{“view_id”=>“1174”}, “91”=>{“view_id”=>“1175”}, “92”=>{“view_id”=>“1177”}, “93”=>{“view_id”=>“1179”}, “94”=>{“view_id”=>“1182”}, “95”=>{“view_id”=>“1185”}, “96”=>{“view_id”=>“1176”}, “97”=>{“view_id”=>“1178”}, “98”=>{“view_id”=>“1181”}, “99”=>{“view_id”=>“1184”}, “100”=>{“view_id”=>“1187”}, “101”=>{“view_id”=>“1180”}, “102”=>{“view_id”=>“1183”}, “103”=>{“view_id”=>“1186”}, “104”=>{“view_id”=>“1080”}, “105”=>{“view_id”=>“1083”}, “106”=>{“view_id”=>“1085”}, “107”=>{“view_id”=>“1081”}},

Wszystkie te rekordy zapisywane sa do bazy z poprawna wartoscia report_workbook_id czy report_view_id.

Jak odfiltrowac te rekordy dla ktorych nie zostala wybrana zadna z opcji pdf, png, xls czy tbw?