Rails – multi selects for associated models

Handling Multiple Selects (or multiple associated attributes) can be quite cumbersome. Ryan Bates has recently wrapped it very nicely in his Complex Forms Screencast. As per that simple way, here’s a how I handle it:

Model:

1234567891011class Project < ActiveRecord::Base....has_many :assigned_taskshas_many :users, :through => :assigned_tasks....def assigned_task_attributes=(assigned_attributes)assigned_attributes.each do |attributes|assigned_tasks.build(attributes)endendend

Controller:
def create @project_task = ProjectTask.new(params[:project_task]) @project_task.save

New/Edit Views:
<%= select_tag("project[assigned_task_attributes][][user_id]", options_for_select(@users.collect{|u| [u.full_name, u.id]}, @project.assigned_tasks.collect{|a| a.user_id} ), {:multiple =>true, :size => 5 }) %>

Adding the virtual attribute in the model saves a ton of (ugly) work in the controller.

UPDATE: Minor tweaks are required for the update operation (remove association collection before updating the model – wrap this in a transaction)