John
John

Reputation: 6612

Form for a has_many :through relation with additional attribute in join table

A question has_many kpi through kpiquestions:

class Question < ActiveRecord::Base
  has_many :kpiquestions, dependent: :destroy
  has_many :kpis, through: :kpiquestions
end

class Kpi < ActiveRecord::Base
  has_many :kpiquestions, dependent: :destroy
  has_many :questions, through: :kpiquestions
end

class Kpiquestion < ActiveRecord::Base
  belongs_to :kpi
  belongs_to :question
end

Now I have a working question form where I can add KPI's by using checkboxes:

= form_for @question do |f|
  = render "layouts/form_messages", target: @question
  .form-group
    = f.label "Name"
    = f.text_field :name
  .form-group
    = f.label "KPI's"
    %ul
      = hidden_field_tag "question[kpi_ids][]", nil
       - @kpis.each do |kpi|
        %li.checkbox
          = check_box_tag "question[kpi_ids][]", kpi.id, @question.kpi_ids.include?(kpi.id), "data-category" => kpi.id
          = kpi.name
  .form-group
      = f.submit(class: 'btn btn-default', value: "Save")

But the join table kpiquestion has an additional attribute weight. This attribute should also be added to the form, with a text_field_tag. Something like this:

= text_field_tag "question[kpi_ids][:weight]", kpi.weight, @question.kpi_ids.include?(kpi.id), "data-category" => kpi.weight 

Obviously this doesn't work, because it now returns an error saying kpi has no attribute called weight. So how can I add this attribute to the form?

Upvotes: 2

Views: 67

Answers (1)

Zubatman
Zubatman

Reputation: 1305

One way would be to make the entire form_for into a form_tag that passes to a post request in the relevant controller, then the only thing limiting which parameters you can pass would be the the params you've chosen to allow controller-side. Obviously this is against convention, but it works great for cases like this.

Here is what the code would change to:

= form_tag question_index_path, :method => :post do
 = render "layouts/form_messages", target: @question *
 .form-group
   = label_tag "Name"
   = text_field_tag :name

 .form-group
   =label_tag :weight
   =text_field_tag :weight

 .form-group
   =label_tag "KPI's"
   = hidden_field_tag "question[kpi_ids][]", nil
   - @kpis.each do |kpi|
    %li.checkbox
      = check_box_tag "question[kpi_ids][]", kpi.id, @question.kpi_ids.include?(kpi.id), "data-category" => kpi.id
      = kpi.name

 .form-group
   =submit_tag("Save", class: btn btn-default)

Upvotes: 1

Related Questions