Noob: UI for many-to-many with has_many :through

Hey All,

I’ve got People and Projects, both of which has_many :through =>
PeopleProjects. PeopleProjects has just one attribute of its own right
now: role (which takes values like ‘programmer’, ‘project manager’
etc.). I believe the models are doing what I need them to–I can add
people to projects (and vice-versa) at the console.

But now I need to add that capability to my views. I’m imagining
something like 2 list boxes, one listing everyone not (yet) assigned to
the project, and the other listing people who are assigned to it. On
this imaginary page I can drag people from one box to the other, and for
those who are assigned to it, easily designate their role with a
drop-down. Of course I’ll settle for check boxes & submit buttons for
managing each list if need be.

I’m assuming there’s no do_what_roy_wants helper for this, so can
anybody point me at tutorials or helpers that do exist that should
help me set something like this up? Or if it’s just not possible w/out
mind-bending Nth-level rails mage skillz, then let me know that.



Roy P.
Research Analyst/Programmer
Group Health Center For Health Studies (Cancer Research Network)
(206) 287-2078
Google Talk: rpardee

Roy -

I had to solve a similar problem this morning with users and mailing
list subscription, where the subscription may have additional parameters
that need to be tracked.

If you take this from the perspective of your People -> Edit view, then
you should be able to include something like this to display a series of
checkboxes showing each project - having it checked if this user belongs
to that project:

 <% for proj in Project.find(:all, :order => :name) %>
    <%= check_box_tag "people[project_ids][]",, 

@people.projects.include?(proj), {:id => “people_project_#{}”} %>
<%= %>
<% end %>

Then in your people_controller.rb, for the ‘update’ action:
def update
@people = People.find(params[:id])
@people.project_ids = params[:people][:project_ids]
if @people.valid?
flash[:notice] = “Updated”
redirect_to :action => ‘index’ and return
render_action ‘edit’

The key is that in your People model (people.rb), you need to set the
attr for storing ‘project_ids’, and create an after save method for
ensuring that the relationships are updated properly:

attr_accessor   :project_ids
after_save      :update_projects

# After_save callback to handle mailinglist_ids
def update_projects
    unless projects_ids.nil?
        self.people_projects.each do |p|
            # delete the existing records if they're not in the 

array of ids to keep
p.destroy unless
# now build up the new associations
project_ids.each do |p|
self.people_project.create(:project_id => p) unless

Hope that helps,

Richard Luck
DiMax, Inc.
Google Talk: dimaxinc

Very helpful–many thanks!

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs