Jay Nguyen
Jay Nguyen

Reputation: 341

Rails - multiple relationships between two models

I have an existing database migration in my app that contains the following contents:

class User < ApplicationRecord
    has_many :courses
end

class Course < ApplicationRecord
    belongs_to :user

    has_and_belongs_to_many :locations
    has_and_belongs_to_many :categories
end

Each user can vote once either like or dislike for a course, so I created a join table in db/migrate:

class CreateUsersCourses < ActiveRecord::Migration[5.0]
    def change
        create_table :users_courses do |t|
        t.integer :course_id, null: false
        t.integer :user_id, null: false
    end
end

Now I am not sure how to add new relationship in User and Course models that does not make it overlapped with the One-Many relationship.

Upvotes: 1

Views: 700

Answers (2)

David Aldridge
David Aldridge

Reputation: 52376

Firstly, don't forget that the associations between classes ought to describe the nature of the association. In this case there are multiple possible associations: a user can create a course, they can vote for a course, and they might study a course. Simple Rails naming conventions for the associations are not going to help you make sense of that.

If a course is created by a single user, then the relationship ought to be that the course :belongs_to :creating_user, and the user has_many :created_courses. You would add a user_id column to the courses table for this.

To allow voting by users on courses, you would use a join table between them. However, your association should describe the nature of the association, so calling the join table user_course_votes would make sense. Then you can have an association on the user of has_many :user_course_votes, and has_many :course_votes, :through :user_course_votes -- and appropriate associations on the course also.

The only thing you need to do to be able to name your associations whatever you like is to name the class or source in the association definition.

class User < ApplicationRecord
  has_many :created_courses, class_name: "Course"
  has_many :user_course_votes
  has_many :course_votes, through: :user_course_votes, source: course
end

This methodology allows you to add other associations between user and course, and assign meaningful names to them that will make your code easier to write and to understand.

Upvotes: 2

ruby_newbie
ruby_newbie

Reputation: 3285

  1. Now you will want to add User has_many :courses, through :user_courses to User.

  2. Create a new migration to add a boolean attribute on User to represent your like/dislike.

  3. Course probably has many users. It would make sense to want to see all of the users of a course.

Upvotes: 0

Related Questions