I have a model called Foo
, which has many bars
. I want to be able to add / remove foo.bars
by adding or removing associated foo.bars.ids
. How can I achieve this?
I tried:
def edit
@bars = @foo.bars
end
<%= form_for @foo, url: edit_foo_path(@foo.id) do |p| %>
...
<%= p.text_area @bars %> #<= returns undefined method `Collection..' for `foo`
...
<%= p.fields_for @foo.bars do |b| %>
<%= b.text_area :ids %> #<= returns in 'unpermitted param 'bar' on #update'
<% end %>
...
<% end %>
I'm thinking fields_for
would not work here anyway since I am not updating bar
's attributes. Instead, I want to be able to add / remove foo.bars
by listings their ids
Hook into the Foo#bar_ids
and Foo#bar_ids=
methods which the has_many association gives you. You could do this via checkboxes for example.
<% form_for @foo do |f| %>
<% @bars.each do |bar| %>
<div class="bar--checkbox">
<%= check_box_tag "foo[bar_ids]", bar.id, @foo.bar_ids.include?(bar.id) %>
<%= bar.name %>
</div>
<% end %>
<%= f.submit "Save" %>
<% end %>
Now, in params you'll get something like
params = {:id => 123, :foo => {:bar_ids => [1, 5, 8, 10]})
and you can do the usual update controller code:
@foo = Foo.where(:id => params[:id])
@updated = @foo.update_attributes(params[:foo])
which is like doing this:
@foo.bar_ids = [1, 5, 8, 10]
@foo.save
NOTE - in your code you're setting @bars to be @foo's current bars. It could be all the bars in the system for example, which would be better in terms of adding and removing whichever bars you want.