Peter Boomsma
Peter Boomsma

Reputation: 9836

Creating a habtm relationship

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

Answers (2)

chumakoff
chumakoff

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

Max Williams
Max Williams

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

Related Questions