# How to map this association

**URL:** <https://www.ruby-forum.com/t/how-to-map-this-association/145572>\
**Category:** Ruby\
**Created:** [August 11, 2008, 5:37pm UTC](https://www.ruby-forum.com/t/how-to-map-this-association/145572 "2008-08-11T17:37:35Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![ybother](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/e274bd/32.png) [@ybother](https://www.ruby-forum.com/u/ybother)\
**Post date:** [August 11, 2008, 5:37pm UTC](https://www.ruby-forum.com/t/how-to-map-this-association/145572/1 "2008-08-11T17:37:35Z")

</div>

Hi, This is the scenario

A user can create videos and collect videos.

I was coding the creation side of the videos so I was using a belongs\_to  
and a has\_many.

Then when I came to the part of collecting the videos, I am stumped with  
how to implement the association.

Normally I would just use a table with user\_id and video\_id.  
But in this case, this would conflict with my earlier code.

so the question is this: how do I implement an association for the  
scenario belong.

A user can create multiple video that are shown on his profile page  
(1 to Many)  
user.rb :has\_many :videos  
video.rb :belongs\_to :user  
user table has a coloum called video\_id

A user can also collect a video. This list is shown as videos favorited  
by this user(Each video can also be favourite by many people)  
(many to many)  
user.rb : has\_and\_belongs\_to\_many :videos  
video.rb :has\_and\_belongs\_to\_many :users  
created a new table called user\_video with user\_id & video\_id

Since the 2 associations are for exactly the same models,  
what happens when I call @user.videos  
will I

1. Get the list of videos created by this user
2. Get the list of videos collected by this user
3. the system goes bonkers ☹

Is this the wrong way to implement this?

---

<div class="post-metadata">

**Author:** ![ybother](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/e274bd/32.png) [@ybother](https://www.ruby-forum.com/u/ybother)\
**Post date:** [August 11, 2008, 10:06pm UTC](https://www.ruby-forum.com/t/how-to-map-this-association/145572/2 "2008-08-11T22:06:34Z")

</div>

Hi,  
I’m guessing this is a Rails question, in which case you should post  
it to the rails list ([http://www.ruby-forum.com/forum/3](http://www.ruby-forum.com/forum/3)). Anyway, since  
the question of ActiveRecord in ruby (sans rails) has been in the news  
so much lately, I guess it couldn’t hurt to answer this here.  
If I understand the problem correctly, you have Users and Videos.  
Videos have a creator (1 creator to many videos) as well as owners (many  
owners to many videos). You were pretty close, except that the since 1  
creator can have many videos you want the Video model to have a field  
e.g. user\_id (or creator\_id), rather than your User model having a  
video\_id field.  
Phill

Wenhan Zhou wrote:

> Hi, This is the scenario
> 
> A user can create videos and collect videos.
> 
> I was coding the creation side of the videos so I was using a belongs\_to  
> and a has\_many.
> 
> Then when I came to the part of collecting the videos, I am stumped with  
> how to implement the association.
> 
> Normally I would just use a table with user\_id and video\_id.  
> But in this case, this would conflict with my earlier code.
> 
> so the question is this: how do I implement an association for the  
> scenario belong.
> 
> A user can create multiple video that are shown on his profile page  
> (1 to Many)  
> user.rb :has\_many :videos  
> video.rb :belongs\_to :user  
> user table has a coloum called video\_id
> 
> A user can also collect a video. This list is shown as videos favorited  
> by this user(Each video can also be favourite by many people)  
> (many to many)  
> user.rb : has\_and\_belongs\_to\_many :videos  
> video.rb :has\_and\_belongs\_to\_many :users  
> created a new table called user\_video with user\_id & video\_id
> 
> Since the 2 associations are for exactly the same models,  
> what happens when I call @user.videos  
> will I
> 
> 1. Get the list of videos created by this user
> 2. Get the list of videos collected by this user
> 3. the system goes bonkers ☹
> 
> Is this the wrong way to implement this?

---

<div class="post-metadata">

**Author:** ![ybother](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/e274bd/32.png) [@ybother](https://www.ruby-forum.com/u/ybother)\
**Post date:** [August 11, 2008, 11:00pm UTC](https://www.ruby-forum.com/t/how-to-map-this-association/145572/3 "2008-08-11T23:00:59Z")

</div>

Hi Wenhan,  
This is how I set up my association and I think it works well… I’m  
using has\_many through instead of has\_and\_belongs\_to\_many. I think that  
using has\_many through is now more widely accepted than it’s  
predecessor.

Anyways, on to the show. Here’s what we have:  
Models

User:  
has\_many :videos, :foreign\_key=\>‘added\_by’ # in retrospect that might  
not be the best name. You could try contributor\_id, maybe.  
has\_many :video\_collections  
has\_many :collected\_videos, :through=\>:video\_collections,  
:source=\>:video # We have to specify a source since we aren’t really  
following the naming convention.

Video:  
belongs\_to :user, :foreign\_key=\>‘added\_by’  
has\_many :video\_collections  
has\_many :collectors, :through=\>:video\_collections,:source=\>:user

VideoCollection:  
belongs\_to :user  
belongs\_to :video

Next up, Simple Migrations for the Models!

Users  
class CreateUsers \< ActiveRecord::Migration  
def self.up  
create\_table :users do |t|  
t.string :name

```
  t.timestamps
end
User.create!(:name=>"Lake")

```

end

def self.down  
drop\_table :users  
end  
end

Videos  
class CreateVideos \< ActiveRecord::Migration  
def self.up  
create\_table :videos do |t|  
t.string :title  
t.integer :added\_by

```
  t.timestamps
end
Video.create!(:title=>"Gone With The Wind", :added_by=>1)

```

end

def self.down  
drop\_table :videos  
end  
end

Video Collections (rumor has it that you can pass :id=\>false here, but I  
forgot to do that when I generated this)  
class CreateVideoCollections \< ActiveRecord::Migration  
def self.up  
create\_table :video\_collections do |t|  
t.integer :user\_id  
t.integer :video\_id

```
  t.timestamps
end
VideoCollection.create!(:user_id=>1, :video_id=>1)

```

end

def self.down  
drop\_table :video\_collections  
end  
end

Okay, so we have our migrations setup and the next thing we cna do is  
Migrate:  
rake db:create:all;rake db:migrate

Then fire up the script/console in your rails\_root directory: ruby  
script/console

Let’s see what happens (ps. We already created some rows in the  
migrations):

#Make sure all our entities are there:

> > User.find(1)  
> > =\> #\<User id: 1, name: “Lake”, created\_at: “2008-08-11 20:53:24”,  
> > updated\_at: “2008-08-11 20:53:24”\>
> 
> > Video.find(1)  
> > =\> #\<Video id: 1, title: “Gone With The Wind”, added\_by: 1, created\_at:  
> > “2008-08-11 20:53:24”, updated\_at: “2008-08-11 20:53:24”\>
> 
> > VideoCollection.find(1)  
> > =\> #\<VideoCollection id: 1, user\_id: 1, video\_id: 1, created\_at:  
> > “2008-08-11 20:53:24”, updated\_at: “2008-08-11 20:53:24”\>

# Check videos associated with users

> > User.find(1).videos  
> > =\> [#\<Video id: 1, title: “Gone With The Wind”, added\_by: 1, created\_at:  
> > “2008-08-11 20:53:24”, updated\_at: “2008-08-11 20:53:24”\>]

# Check user associated with video

> > Video.find(1).user  
> > =\> #\<User id: 1, name: “Lake”, created\_at: “2008-08-11 20:53:24”,  
> > updated\_at: “2008-08-11 20:53:24”\>

# Check collected videos associated with user

> > User.find(1).collected\_videos  
> > =\> [#\<Video id: 1, title: “Gone With The Wind”, added\_by: 1, created\_at:  
> > “2008-08-11 20:53:24”, updated\_at: “2008-08-11 20:53:24”\>]

# Check collector associated with video

> > Video.find(1).collectors  
> > =\> [#\<User id: 1, name: “Lake”, created\_at: “2008-08-11 20:53:24”,  
> > updated\_at: “2008-08-11 20:53:24”\>]

# Let’s make sure we really are getting different associations since

it’s only fairly proven.

# Let’s create a new video

> > Video.create!(:title=\>‘Gone With The Wind’, :added\_by=\>2)  
> > =\> #\<Video id: 2, title: “Gone With The Wind”, added\_by: 2, created\_at:  
> > “2008-08-11 20:58:43”, updated\_at: “2008-08-11 20:58:43”\>

# Let’s create a new video collection for user 1 and video 2

> > VideoCollection.create(:user\_id=\>1, :video\_id=\>2)  
> > =\> #\<VideoCollection id: 2, user\_id: 1, video\_id: 2, created\_at:  
> > “2008-08-11 20:59:26”, updated\_at: “2008-08-11 20:59:26”\>

# Now let’s ask the user for it’s collected videos

> > User.find(1).collected\_videos  
> > =\> [#\<Video id: 1, title: “Gone With The Wind”, added\_by: 1, created\_at:  
> > “2008-08-11 20:53:24”, updated\_at: “2008-08-11 20:53:24”\>, #\<Video id:  
> > 2, title: “Gone With The Wind”, added\_by: 2, created\_at: “2008-08-11  
> > 20:58:43”, updated\_at: “2008-08-11 20:58:43”\>]

# And now for User 1’s videos that he added

> > User.find(1).videos  
> > =\> [#\<Video id: 1, title: “Gone With The Wind”, added\_by: 1, created\_at:  
> > “2008-08-11 20:53:24”, updated\_at: “2008-08-11 20:53:24”\>]

Hope that helps some.

Lake

Wenhan Zhou wrote:

> Hi, This is the scenario
> 
> A user can create videos and collect videos.
> 
> I was coding the creation side of the videos so I was using a belongs\_to  
> and a has\_many.
> 
> Then when I came to the part of collecting the videos, I am stumped with  
> how to implement the association.
> 
> Normally I would just use a table with user\_id and video\_id.  
> But in this case, this would conflict with my earlier code.
> 
> so the question is this: how do I implement an association for the  
> scenario belong.
> 
> A user can create multiple video that are shown on his profile page  
> (1 to Many)  
> user.rb :has\_many :videos  
> video.rb :belongs\_to :user  
> user table has a coloum called video\_id
> 
> A user can also collect a video. This list is shown as videos favorited  
> by this user(Each video can also be favourite by many people)  
> (many to many)  
> user.rb : has\_and\_belongs\_to\_many :videos  
> video.rb :has\_and\_belongs\_to\_many :users  
> created a new table called user\_video with user\_id & video\_id
> 
> Since the 2 associations are for exactly the same models,  
> what happens when I call @user.videos  
> will I
> 
> 1. Get the list of videos created by this user
> 2. Get the list of videos collected by this user
> 3. the system goes bonkers ☹
> 
> Is this the wrong way to implement this?
