Posts Rails many-to-many associations
Post
Cancel

Rails many-to-many associations

The tables:

developer (...)  
functional_system (...)  
developers_function_systems (developer_id, functional_system_id)  

I used “functional_system” instead of simply “system”, because it was giving me errors as it is one of Rails reserved words - something I don’t like about Rails.

The models

class FunctionalSystem < ActiveRecord::Base
	has_and_belongs_to_many :developers
end

class Developer < ActiveRecord::Base
	has_and_belongs_to_many :functional_systems
end

The View (templates)

I included the checkboxes representing developers working on the same system:

...
<% Developer.find(:all).each do |developer| %>
   <li><%= check_box_tag(”functional_system[developer_ids][]“, developer.id, @functional_system.developers.include?
(developer))%> <%= developer.name %></li>
<% end %>
..

The Controller

...
@functional_system = FunctionalSystem.new(params[:functional_system])
...

Rails has recognized the request parameters and magically filled out the @functional_system.developers collection.

A problem occurred when I wanted to include the join_date in the association information. That is the developers_functional_systems has an additional field of join_date. After trying out several scenarios - I finally came across push_with_attribute.

Adding the following lines to the controller

@functional_system = FunctionalSystem.new(params[:functional_system])
#developers collection need to be cleared. Otherwise a "Duplicate Entry" error will be returned
@functional_system.developers.clear
params[:functional_system][:developer_ids].each do |dev_id|
	@functional_system.developers.push_with_attributes(Developer.find(dev_id), {"join_date" => Date.today});
end

This performs what Rails has previously done automagically. It added a new developers_functional_systems’s entry (explicitly), with the additional association info of join_date.

As a more friendly approach, and to make use of Rails magic, It was better off adding the “join_date” in the view.

The naming convention is a bit tricky, after several trials, this have worked:

<% Developer.find(:all).each do |developer| %>
<li><%= check_box_tag("functional_system[developer_ids][]", developer.id, @functional_system.developers.include?(developer)) %><%= developer.name %></li>
<input type="hidden" name="developers[join_dates][]" value="<%= Date.today %>">
<% end %>

I’m still not sure how the hash represented by name=”developers[join_dates][]” is recognized as belonging to the current functional_system. Does anyone have a clue?

Contents

Search Results