Associations two-many-to-many - ruby-on-rails

I don't fully understand how associations work.
I have 3 models:
Movie (:about, :title, :url, :actors, :uploader)
Actor (:birth, :name)
Relationships (:actor_id, :film_id)
Relationships is the association between Movies and Actors, so "which actor play in which movie". My teacher told me I can make it easier with http://railscasts.com/episodes/47-two-many-to-many but I don't know how to use that, any idea?

I would imagine you want something like:
class Movie < ActiveRecord::Base
has_many :actors, :through => :relationships
end
class Relationship < ActiveRecord::Base
belongs_to :movie
belongs_to :actor
end
class Actor < ActiveRecord::Base
has_many :movies, :through => :relationships
end
http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association
Or alternatively, if you don't feel you have to define the relationship class explicitly, you can simply use has_and_belongs_to_many:
class Movie < ActiveRecord::Base
has_and_belongs_to_many :actors
end
class Actor < ActiveRecord::Base
has_and_belongs_to_many :movies
end

Related

Rails type of relation between models

I have 3 models: User, Order and Car and I have question because I don't know what relationships between these models will be the best. Only requirement is that only one car per user in order.
A user can have many orders, and therefore, many cars through those orders.
class User < ActiveRecord::Base
has_many :orders
has_many :cars, through: :orders
end
An order belongs to a user and a car.
class Order < ActiveRecord::Base
belongs_to :user
belongs_to :car
end
A car has one order.
class Car < ActiveRecord::Base
has_one :order
end
So you need one on one relationship between order and car and then back to order and customer one relationship. Something below should do the trick.
class Car < ActiveRecord::Base
has_one :order
has_one :customer, through: :order
end
class Order < ActiveRecord::Base
belongs_to :car
belongs_to :customer
end
class Customer < ActiveRecord::Base
has_one :order
has_one :car , through: :order
end
But i will suggest the has_many relationship by the looks of the model name, but you know better your problem than me.

Should this has_many :through relationship be polymorphic or not?

I have a many-to-many relationship setup for Teachers and Classrooms via has_many :through:
class Teacher < ActiveRecord::Base
has_many :classrooms, :through => :classroom_memberships
end
class Classroom < ActiveRecord::Base
has_many :students
has_many :teachers, :through => :classroom_memberships
end
class ClassroomMemberships < ActiveRecord::Base
belongs_to :teacher
belongs_to :classroom
end
Currently, Students can only belong to one Classroom:
class Student < ActiveRecord::Base
belongs_to :classroom
end
Now I have the need to track historical classroom memberships for students, creating a second many-to-many relationship for classrooms. So, while a student can only belong to one classroom at a time, I need to know that last year, student A belonged to classroom B.
I'm thinking I have two viable options:
1.) Make the classroom_memberships association polymorphic so I'd have a classroomable_id and classroomable_type that would point to either a teacher OR a student.
2.) Simplify things and add another foreign key to ClassroomMemberships called student_id, in which case, for a given row, either student_id OR teacher_id would have a value.
Which is the better option?
I would probably go the route of:
class Course < ActiveRecord::Base
# like "MATH 100"
has_many :sections
has_many :teachers, :through => :sections
end
class Term < ActiveRecord::Base
# like "Fall 2015"
has_many :sections
end
class Teacher < ActiveRecord::Base
has_many :sections
has_many :courses, :through => :sections
end
class Section < ActiveRecord::Base
# a course, in a term, taught by a teacher, with registered students
belongs_to :term
belongs_to :course
belongs_to :teacher
has_many :registrations
has_many :students, :through => :registrations
end
class Registration < ActiveRecord::Base
# a student in a specific section
belongs_to :section
belongs_to :student
end
class Student < ActiveRecord::Base
# a student's registrations are their course history
has_many :registrations
has_many :sections, through :registrations
end
As a start, since this is a fairly basic modeling of an educational system.
It sounds like maybe you want a ClassroomMembershipHistory model.
Something like
class ClassroomMembershipHistory < ActiveRecord::Base
belongs_to :student
belongs_to :classroom
end
with a year attribute, stored however is easiest to query for your use case.

How to get relation attributes joined together in rails?

I have this type of relation in my models:
class Movie < ActiveRecord::Base
  has_many :movie_genres
  has_many :genres, through: :movie_genres
end
 
class MovieGenre < ActiveRecord::Base
  belongs_to :movie
  belongs_to :genre
end
 
class Genre < ActiveRecord::Base
  has_many :movie_genres
end
So I am assigning multiple genres to a movie. Also the model MovieGenre has additional columns/attributes like "sort_order" which descripe the order/priority of an genre for a move. So far I can retrieve the genres and I can retrieve the relations (MovieGenre-records) by simply calling #movie.genres or *#movie.movie_genres* but how can I join those two informations and retrieve them together?
So far I saw myself forced to manually search the *movie_genre* record for every genre. Is there a way so that I can get those together so that I have for example the genre.name available together with movie_genre.sort_order?
What would be the rails way or maybe there even exists some rails magic for that?
You've got your associations wrong:
class Movie < ActiveRecord::Base
has_many :movie_genres
has_many :genres, through: :movie_genres
end
class MovieGenre < ActiveRecord::Base
belongs_to :movie
belongs_to :genre
end
class Genre < ActiveRecord::Base
has_many :movie_genres
has_many :movies, through: :movie_genres
end
I haven't tested this, but you must use singulars on the through model associations. (And I've added the "has_many :movies" on Genre for symmetry.
And to read the attributes:
#movie.movie_genres.count # => 3
#movie.movie_genres.first # => MovieGenre
#movie.movie_genres.first.genre # => Genre

Active Record, count of grandchild association record

Let's say I've got:
class Town < ActiveRecord::Base
has_many :citizens
end
class Citizen < ActiveRecord::Base
belongs_to :town
has_many :cars
end
class Car < ActiveRecord::Base
belongs_to :citizen
end
Using ActiveRecord, what is the simplest way I can get a count of cars in the town?
In your models you can define a through association.
class Town < ActiveRecord::Base
has_many :citizens
has_many :cars , :through => :citizens
end
And query like this.
#town.cars.count
or
Town.find("town id").cars.count

Rails/Active Record polymorphic association needed?

I have 3 models, a School which has many Teachers and Students. The problem is that Students can belong to either a School or a Teacher, so theoretically they always belong to a School through association. How would I deal with this type of data structure in Rails/Active Record?
class School < AR::Base
has_many :teachers
has_many :students
end
class Teacher < AR::Base
belongs_to :school
has_many :students
end
class Student < AR::Base
belongs_to ???
end
This solution should work, but you I have a doubt about your introduction ; you say that "a teacher have many student". This sentences implies "a student has ONE teacher".
Maybe you should set an has_and_belongs_to_many association.
class School < AR::Base
has_many :teachers
has_many :students, :through => :teachers
end
class Teacher < AR::Base
belongs_to :school
has_many :students
end
class Student < AR::Base
belongs_to :teacher
belongs_to :school, :through => :teacher
end
Clearly you need polymarphic association, can be done as
class School < AR::Base
has_many :teachers
has_many :students, :as => :studentable
end
class Teacher < AR::Base
belongs_to :school
has_many :students
end
class Student < AR::Base
belongs_to :studentable
end
don't forget to add studentable_id and studentable_type to student model.

Resources