Has_many :through questions

I’ve created the following associations using :through:

class Person < ActiveRecord::Base
  has_many :attendees, :dependent => :destroy
  has_many :events, :through => :attendees, :uniq => true
end

class Event < ActiveRecord::Base
  has_many :attendees, :dependent => :destroy
  has_many :people, :through => :attendees, :uniq => true
end

class Attendee < ActiveRecord::Base
  belongs_to :event
  belongs_to :person
end

The database tables are as follows:

ActiveRecord::Schema.define(:version => 3) do

create_table “attendees”, :id => false, :force => true do |t|
t.column “event_id”, :integer
t.column “person_id”, :integer
t.column “bit_flags”, :integer
end

add_index “attendees”, [“event_id”], :name =>
“index_attendees_on_event_id”
add_index “attendees”, [“person_id”], :name =>
“index_attendees_on_person_id”

create_table “events”, :force => true do |t|
t.column “name”, :string
t.column “description”, :text
t.column “event_date”, :date
t.column “start_time”, :time
t.column “end_time”, :time
t.column “last_register_date”, :date
t.column “location_city”, :string
t.column “location_state”, :string, :limit => 2
t.column “location_zip”, :string, :limit => 9
t.column “location_addr”, :text
t.column “agenda”, :text
t.column “contacts”, :text
end

create_table “people”, :force => true do |t|
t.column “first_name”, :string
t.column “last_name”, :string
t.column “title”, :string
t.column “organization”, :string
t.column “email”, :string
t.column “phone1”, :string
t.column “phone2”, :string
end

end

I wanted to use the following method which the documentation indicates
is available for has-many associations. (See (http://
rails.rubyonrails.com/classes/ActiveRecord/Associations/
ClassMethods.html) :

collection=objects - replaces the collections content by deleting

and adding objects as appropriate.

That’s because I want to eliminate redundant join records, i.e., there
should be only one record in the attendees table that contains the
combination of event_id=1 and person_id=1. I took “deleting and
adding objects as appropriate” to mean that. Is this true?

Secondly, trying this code in class PeopleController:

@person.events = Event.find(@params[:event_ids]) if

params[:event_ids]

resulted in the following error:

undefined method `events=' for #<Person:0x6836228>

So, did I get something wrong or is this method not available
with :through associations?

If not available, is there another (best?) method or combination that
would maintain the attendees table so that event_id + person_id
combinations are unique?

btw, I also tried the following:

@person.events << Event.find(params[:event_ids]) if

params[:event_ids]

It works, but adds (appends) join records without regard to
uniqueness.

Thanks,
Stan

I solved as follows (not sure it’s the best approach):

def create
@person = Person.new(params[:person])
@events = params[:event_ids] if params[:event_ids]

# Create attendee record for each selected event
if @person.save
  if @events != nil then
    @events.each { |event|
      @person.events.push (Event.find(event))
    }
  end
  flash[:notice] = 'Person was successfully created.'
  redirect_to :action => 'list'
else
  render :action => 'new'
end

end

def update
@person = Person.find(params[:id])
@events = params[:event_ids] if params[:event_ids]
if @events != nil then
@events.each { |event|
if !Attendee.exists?(:person_id => @person, :event_id => event)
@person.events.push (Event.find(event))
end
}
end

if @person.update_attributes(params[:person])
  flash[:notice] = 'Person was successfully updated.'
  redirect_to :action => 'show', :id => @person
else
  render :action => 'edit'
end

end