Two Linked Models + User Model? - ruby-on-rails

I am trying to create the following basic structure with RoR. The key is that all Users also be linked to a School and a Major. Users will write articles based on their School and Major. The linking is not exclusive: many users can be in one of many schools, and one of many majors. However, each user cannot be in more than one school, and cannot be in more than one major. Eventually, I would like to be able to show posts/filter articles based on the following:
All Users in both Major X and at School Y
All Majors at School Y
All Schools with Major X
I've done a little research, not sure if any of this is correct... (still learning) should I be using has_and_belongs_to_many below as compared to has_many?
Table
major_schools #(linking the two models below)
Models
class School < ActiveRecord::Base
has_many :major_schools
has_many :majors, :through => :major_schools
end
class Major < ActiveRecord::Base
has_many :major_schools
has_many :schools, :through => major_schools
end
#school.majors #now gives a list of all the majors this school has
#major.schools #still gives a list of all schools that have this major
What I need to do is also incorporate a user model with the two above:
class User < ActiveRecord::Base
has_and_belongs_to_many :major_schools
end
And I am quite stuck... How can I pull in the User model data to the above models?

Your domain model is a tad tangled here, but it works.
Here is one way to load all Users in both Major with id X and at School with id Y:
class MajorSchool < ActiveRecord::Base
belongs_to :major
belongs_to :school
has_and_belongs_to_many :users
end
# Load all users from this school/major combination
MajorSchool.where(major_id: X, school_id: Y).users

Why not simply do:
class School < ActiveRecord::Base
has_many :major_schools
has_many :majors, :through => :major_schools
has_many :users
end
class Major < ActiveRecord::Base
has_many :major_schools
has_many :schools, :through => major_schools
has_many :users
end
class User < ActiveRecord::Base
belongs_to :school
belongs_to :major
end
Then you should be able to do:
# all students of the school
#school.users
# all students of the school and major (each line should return the same results)
#school.users.where(major_id: #major.id)
#major.users.where(school_id: #school.id)
User.where(school_id: #school.id, major_id: #major.id)

Related

How to reference a field in the join model of a has_many though Rails 5 relationship

I am working on an app where users have many quizzes and quizzes can have many users. I have set the relationships:
class User < ApplicationRecord
has_many :studies
has_many :quizzes, through: :studies
end
class Quiz < ApplicationRecord
has_many :studies
has_many :users, through: :studies
end
class Study < ApplicationRecord
belongs_to :user
belongs_to :quiz
end
I have a field in the Study table to store the score that the user made on the quiz, but I am unable to access the field. I have tried #quiz.studies.score and #quiz.study.score but Rails give me an undefined method. How to I access the field in a join model of a has_many though relationship?
#quiz.studies return the collection of studies. So you have to use first, last, each to get the score of the specific studies.
Try this:
#quiz.studies.first.score

Rails associations, has_one to has_many

In my app I have 2 classes. User and Classroom. I use the user class as a student as well.
I'm trying to achieve a result where:
A classroom belongs to a user.
A user has many classrooms.
A classroom has one student through the user class.
A student can be associated to many classrooms.
To try and explain further. I have a classroom and the user is the creator of the classroom. When someone joins they are a student of the classroom and I only want there to be one student and one creator.
I want a student to be attached to lots of different classrooms and I want the classrooms to all belong to one user.
My current code for the two classes looks like this:
class User < ActiveRecord::Base
has_many :classrooms
end
class Classroom < ActiveRecord::Base
belongs_to :user
has_one :student, :class_name => "User"
end
Any advice is much appreciated. Thanks!
I think what you are trying to achieve is:
class User < ActiveRecord::Base
has_many :classroom_users
has_many :classrooms, through: :classroom_users
end
class ClassroomUser < ActiveRecord::Base
belongs_to :classroom
belongs_to :user
end
class Classroom < ActiveRecord::Base
has_many :classroom_users
has_many :users, through: :classroom_users
end

Which Association Should I Use?

My app has 5 core models. I'm trying to figure out the best way to associate the models. How many tables should I build and which kind etc?
Here are the associations I would like to include and their respective models:
User
Has many boards
Has many lists
Has many cards
Has many comments
Board
Has many users
Has many lists
Has many cards
List
Belongs to board
Has many cards
Card
Belongs to board
Belongs to list
Has many comments
Comment
Belongs to card
Belongs to user
class User < ActiveRecord::Base
has_and_belongs_to_many :boards
has_many :lists, as: listable
has_many :cards, as: cardable
has_may :comments, as: commentable
end
class Board < ActiveRecord::Base
has_and_belongs_to_many :users
has_many :lists, as: listable
has_many :cards, as: cardable
end
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class List < ActiveRecord::Base
belongs_to :listable, :polymorphic => true
has_many :cards, as: cardable
end
class Card < ActiveRecord::Base
belongs_to :cardable, :polymorphic => true
has_many :comments, as:commentable
end
To establish HABTM relation you have to create a table named 'users_boards'
As Board and User are having many to many relationship, there will be a new table for it, if you want HABTM you can use it.
User(id, name, other_attributes...)
Board(id, name,...)
List(id, name, user_id(fk),...)
Card(id, name, user_id(fk), list_id(fk), board_id(fk),...)
Comment(id, comment_msg, user_id(fk), card_id(fk),...)
Board_User(board_id(fk), user_if(fk)) --- M-M relation
Few attributes might change if there is a has_many through relation.
FK-- Foreign key, you can use has_many through depending on your requirements.
Using polymorphic associations has some limitations, so please do through it then decide to use a polymorphic association
http://codeblow.com/questions/pros-and-cons-for-ruby-on-rails-polymorphic-associations/

has_many :through relationships explained

I'm new to Rails and have some doubts about the kind of relationship do I need to use. Here is the case.
I have two models Offer and User, a user could belong to to many offers and offers can have many user. Also the users create the offers.
I think I have to use a has_many :through ralationship. For example I've created another model "Applicant". Applicant belongs_to user and belongs_to offer. But how is the relationship from the user and offer model? For example:
User Model
has_many :offer, :through => :applicant
Offer Model
has_many :user, :through => :applicant
My doubt is because I already have this two relationship
User Model
has_many :offers, :dependent => :destroy
Offer Model
belongs_to :user
After solve this, I guest I have to save the record in the applicant model from the applicanst_controller, right?
Thanks in advance
What you have described is a many-to-many relationship using a join table. You're actually pretty close but you just need to remove the has_many :offers, :dependent => :destroy from your user model and the blongs_to :user in your offer model. It should look something like this:
class User < ActiveRecord::Base
has_many :offers, :through => :applicants
end
class Applicant < ActiveRecord::Base
belongs_to :users
belongs_to :offers
end
class Offer < ActiveRecord::Base
has_many :users, :through => :applicants
end
You don't have to worry about the dependent destroy part as associations are automatically removed as the corresponding objects are removed. With a many to many association it doesn't really matter how you go about building the relationship. Either of the following will work:
#user.offers << #offer
#offers.users << #user
If you don't need to store any information specific to your applicant join table (e.g., time stamps, descriptions) you might instead want to look at a has_and_belongs_to_many relationship. Check out choosing between has_many_through and has_and_belongs_to_many for reference.
Edit
Heres the code for a HABTM relationship:
class User < ActiveRecord::Base
has_and_belongs_to_many :offers
end
class Offer < ActiveRecord::Base
has_and_belongs_to_many :users
end

Ruby on Rails 3.1: Am I setting this relationship up correctly?

I am making my first app in Ruby on Rails 3.1....Do I have these relationships setup correctly? Essentially, a student/client will be able to login and rate a teacher. A client can have many teachers and a teacher can have many clients. Each client can create a rating for a particular teacher (a teacher can't rate clients). Ratings are optional.
I intend to be able to display a teacher's ratings from various clients and also allow clients to login and rate all the teachers they've had.
class Client < ActiveRecord::Base
has_many :ratings
has_and_belongs_to_many :teachers
end
class Teacher < ActiveRecord::Base
has_many :ratings
has_and_belongs_to_many :clients
end
class Rating < ActiveRecord::Base
belongs_to :teacher
belongs_to :client
end
I'd say that the usage of has_and_belongs_to_many should be used when you only have a database table and not a Rails model to join the models. In your case, since you do have a model called Rating then I'd say it is better to use has_many, :through.
To accomplish that, change your Teacher and Client models to look like this:
class Client < ActiveRecord::Base
has_many :ratings
has_many :teachers, :through => :ratings
end
class Teacher < ActiveRecord::Base
has_many :ratings
has_many :clients, :through => :ratings
end
The Rating model does not need any changing.

Resources