Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using check boxes with a has_many relationship

I have an invoice with some lines. A line can only belong to one invoice. This is how my schema looks like:

create_table "invoices" do |t|
end

create_table "lines" do |t|
  t.integer  "invoice_id"
end

And my models:

class Invoice < ActiveRecord::Base
  has_many :lines
end

class Line < ActiveRecord::Base
  belongs_to :invoice
end

Now, when creating (or editing) an invoice I would like to show a list with all possible lines (the lines already exist in the database) and have a check box for each line to link it with the invoice.

I had a look at the HABTM problem but I don't think that's what I need here, the problem isn't as complex. I think the problem is me wanting to update the Unit#invoice_id while I am working on the invoice. Can I do this with a nested form or do I need a before_save callback here?

Thanks!

like image 329
Cimm Avatar asked Nov 28 '22 03:11

Cimm


2 Answers

Have a look at Iain's answer. It's definitely the right way to go but... I prefer not to use simple_form or formtastic for this example to keep it as simple as possible.

I used Iain's HTML output to extract the HTML I need. This snippet is the same as Iain's answer without the need of an extra library:

<% Line.all.each do |line| %>
  <%= hidden_field_tag "invoice[line_ids][]" %>
  <%= check_box_tag "invoice[line_ids][]", line.id, @invoice.lines.include?(line), :id => "invoice_line_ids_#{line.id}" %>
<% end %>

PS: The Line.all and @invoice.lines... should be extracted to the controller and invoice model, they don't belong in the view. They are only used for brevity's sake.

like image 56
Cimm Avatar answered Nov 30 '22 18:11

Cimm


A has_many association also adds the accessor line_ids, which you can create check boxes for.

If you're using simple_form or formtastic it's incredibly easy:

<%= f.input :line_ids, :as => :check_boxes %>

Which will create something like this:

<span>
  <input name="invoice[line_ids][]" type="hidden" value="" />
  <input checked="checked" class="check_boxes optional" id="invoice_line_ids_1" name="invoice[line_ids][]" type="checkbox" value="1" />
  <label class="collection_check_boxes" for="invoice_line_ids_1">Line Name 1</label>
</span>

<span>
  <input name="invoice[line_ids][]" type="hidden" value="" />
  <input checked="checked" class="check_boxes optional" id="invoice_line_ids_2" name="invoice[line_ids][]" type="checkbox" value="2" />
  <label class="collection_check_boxes" for="invoice_line_ids_2">Line Name 2</label>
</span>

And that is all there is to it. No nested forms or anything else needed.

like image 38
iain Avatar answered Nov 30 '22 17:11

iain