Reputation: 9836
I'm creating a movie watchlist app in rails/angular. For this I have a table with users and a table with movies.
At the moment I create a unique record for each movie added, this results in several copies of existing records but all with different user id's. So I'm looking into the has_and_belongs_to_many relationship in rails. But I'm having some trouble using it in my app.
As I see it a user can have multiple movies, and a movie can have multiple users. So I've added this to the models,
movie.rb
has_and_belongs_to_many :users
user.rb
has_and_belongs_to_many :movies
I've also created a migration,
class AddMoviesUsersJoinTable < ActiveRecord::Migration
def self.up
create_table :movies_users, :id => false do |t|
t.integer :movie_id
t.integer :user_id
end
end
def self.down
drop_table :movies_users
end
end
But I'm unsure on how this is all connected. With the migration I've added a join table with 2 colums. Movie_id and user_id. Does the movie_id
value in the movie_users
table correspond to the movie_id
in the movie table
? Same goes for the user_id
, does that correspond to the user_id
in the user table
?
Also, how do I connect the two id's together. Do I have to add "something" to the movies_users
join table when I create a new movie?
This is my current movies_controller.rb
def create
respond_with Movie.create(movie_params.merge(user_id: current_user.id))
end
private
def movie_params
params.require(:movie).permit(:title, :image, :release_date, :movie_id)
end
//EDIT//
I've added the has_many_belongs_to
relations to my movie and user model and I created a join table called movies_users
with 2 colums user_id
and movie_id
.
I've created 2 accounts on my page and added the movie Creed with them. This is the result in my rails console Movie.all
#<Movie id: 1, title: "Creed", user_id: 1, movie_id: "312221">,
#<Movie id: 2, title: "Creed", user_id: 2, movie_id: "312221">
As you can see it still creates 2 different movies although they have the same values, except the user_id. So it looks like there's no checking to see if an value (the movie_id
) already exists. I thought this was a part of the habtm relation.
Upvotes: 2
Views: 930
Reputation: 7054
It is fine to use habtm
in your case if you need the join table only for relationships and don't need to store extra information in the joining table. In this c\\ase records of the joining table (movies_users) are created automatically, while you are using given by the has_and_belongs_to_many
methods.
Your create
action may look like this:
def create
movie = Movie.create(movie_params)
current_user.movies << movie
...
end
or like this:
def create
current_user.movies.create(movie_params)
...
end
Added after the question updated
You don't need movie_id
and user_id
fields in your Movie model. This all should look like this:
movie = Movie.last
#<Movie id: 1, title: "Creed">
user = User.last
#<User id: 1, name: "Username", ...>
# add the movie to the user's watch list
user.movies << movie
# a record in the joining table will be created automatically
#<user_id: 1, movie_id: 1>
Upvotes: 1
Reputation: 32955
Rather than habtm i would use has_many :through
class User
has_many :movies_users
has_many :movies, :through => :movies_users
class Movie
has_many :movies_users
has_many :users, :through => :movies_users
class MoviesUser
belongs_to :movie
belongs_to :user
Now you will have a single movie record per movie and create a movie_user record when a user watches a movie. You can do this RESTfully with a MoviesUsersController, which you call the create action, passing through params = {:movies_user => {:user_id => 123, :movie_id => 456}}
Upvotes: 4