How to map this association

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 :frowning:

Is this the wrong way to implement this?

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). 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 :frowning:

Is this the wrong way to implement this?

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 :frowning:

Is this the wrong way to implement this?