Right way to do many-to-many relationships (long post)

I’m struggling with some older Rails code. It’s buggy and I don’t find a
way
to get it better.
The project is centered around the assignment of projects to students at
a
university. I have a class Researchgroup:
class ResearchGroup < ActiveRecord::Base
has_many :people
has_many :projects
end

(I don’t completely agree with the last association, but that’s a
different
problem.)

The person class:

class Person < ActiveRecord::Base
belongs_to :research_group
has_many :connections, :dependent => :delete_all
end

The connection class:
class Connection < ActiveRecord::Base
belongs_to :person
belongs_to :project
end

The connection table has a field kind that denotes the association of
that
person to a project. Is that a right way to handle this association? It
seems pretty hard to do this properly in Rails…

Now the project_controller has the following complicated new method:

def create
@project = Project.new(params[:project])
// create a project with the research group set to to the first
promotor,
which comes from the form as an AJAX-enabled comma-separated field, if
you
have group permissions
if authenticate_as_group and (params[:connection][:promotors] !=
‘’)
@project.research_group_id =
Person.find_by_name((params[:connection][:promotors]).split(/,\s*/
[0]).research_group_id
else
// set promotor to your group
@project.research_group_id =
Person.find_by_login(session[:login]).research_group_id
end
// the previous part gives problems if the first promotor is not in the
DB…
if @project.save
if !(params[:connection][:promotors] == ‘’)
for promotor in
(params[:connection][:promotors]).split(/,\s*/)
person = Person.find_by_name(promotor)
if !(person == nil)
if authenticate_as_group or (authenticate_as_normal and
(person.research_group_id ==
Person.find_by_login(session[:login]).research_group_id))
begin
connection = Connection.new(:project_id =>
@project.id, :person_id => person.id, :kind => ‘p’)
connection.save
rescue
end
end
end
end
end
if !(params[:connection][:copromotors] == ‘’)
for copromotor in (params[:connection][:copromotors]).split(/
\s*/)
person = Person.find_by_name(copromotor)
if !(person == nil)
if authenticate_as_group or (authenticate_as_normal and
(person.research_group_id ==
Person.find_by_login(session[:login]).research_group_id))
begin
connection = Connection.new(:project_id =>
@project.id, :person_id => person.id, :kind => ‘c’)
connection.save
rescue
end
end
end
end
end
if !(params[:connection][:supervisors] == ‘’)
for supervisor in (params[:connection][:supervisors]).split(/
\s*/)
person = Person.find_by_name(supervisor)
if !(person == nil)
if authenticate_as_group or (authenticate_as_normal and
(person.research_group_id ==
Person.find_by_login(session[:login]).research_group_id))
begin
connection = Connection.new(:project_id =>
@project.id, :person_id => person.id, :kind => ‘s’)
connection.save
rescue
end
end
end
end
end
if !(params[:external_connection][:promotors] == ‘’)
connection = ExternalConnection.new(:project_id =>
@project.id, :people => params[:external_connection][:promotors], :kind
=> ‘p’)
connection.save
end
if !(params[:external_connection][:copromotors] == ‘’)
connection = ExternalConnection.new(:project_id =>
@project.id, :people => params[:external_connection][:copromotors],
:kind
=> ‘c’)
connection.save
end
if !(params[:external_connection][:supervisors] == ‘’)
connection = ExternalConnection.new(:project_id =>
@project.id, :people => params[:external_connection][:supervisors],
:kind
=> ‘s’)
connection.save
end
flash[:color] = ‘green’
flash[:notice] = ‘Project created succesfully.’
redirect_to :action => ‘show’, :id => @project
else
render :action => ‘new’
end
end

I don’t like this code at all. Any suggestions to handle the specific
problems (proper validation of the promotor line, cleaner associations)
or
to improve this code are more than welcome.
If you need more information on this problem do not hesitate to ask for
it,
I’m really keen on properly deploying a Rails app. Currently I feel this
thing would give Rails a bad image here…

Bart

Bart B. wrote:

I don’t like this code at all. Any suggestions to handle the specific
problems (proper validation of the promotor line, cleaner associations)
or
to improve this code are more than welcome.
If you need more information on this problem do not hesitate to ask for
it,
I’m really keen on properly deploying a Rails app. Currently I feel this
thing would give Rails a bad image here…

Bart

Bart,

Have you ever come across this useful PDF:
http://jrhicks.net/Projects/rails/has_many_and_belongs_to_many.pdf

I didn’t have time to have a really good look through the code, and I’d
like to take a closer look at the DB schema behind those models, but
there did seem to be a possibility that at least some of the
associations should either be has_and_belongs_to_many or has_many
:through

See here for the differences in those associations:
http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off