# Has\_many :through questions

**URL:** <https://www.ruby-forum.com/t/has-many-through-questions/121036>\
**Category:** Rails\
**Created:** [November 23, 2007, 12:55am UTC](https://www.ruby-forum.com/t/has-many-through-questions/121036 "2007-11-23T00:55:01Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![stan.baptista](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ccd318/32.png) [@stan.baptista](https://www.ruby-forum.com/u/stan.baptista)\
**Post date:** [November 23, 2007, 12:55am UTC](https://www.ruby-forum.com/t/has-many-through-questions/121036/1 "2007-11-23T00:55:01Z")

</div>

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/](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

---

<div class="post-metadata">

**Author:** ![stan.baptista](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ccd318/32.png) [@stan.baptista](https://www.ruby-forum.com/u/stan.baptista)\
**Post date:** [November 24, 2007, 2:19am UTC](https://www.ruby-forum.com/t/has-many-through-questions/121036/2 "2007-11-24T02:19:02Z")

</div>

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
