What is the correct rails model? Using redundancy recommended? - ruby-on-rails

In my rails application Company acts as the user model. A company can have many customers and many employees (carseller).
There is a many to many relation between a carseller and a customer.
There is the following problem: A lot of times i'd have to retrieve all the appointments made with the whole company. Since there is no company_id saved in the appointment model this can be quite painful.
Should i just include a foreign key to company in the appointments and have some form of redundancy or is there another easy and efficient way?
class Company < ActiveRecord::Base
has_many :customers
has_many :carseller
end
class Customer < ActiveRecord::Base
belongs_to :company
has_many :appointments
has_many :carsellers, :through => :appointments
end
class Carseller < ActiveRecord::Base
belongs_to :company
has_many :appointments
has_many :customers, :through => :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :customer
belongs_to :carseller
end

I think you can use :
class Appointment < ActiveRecord::Base
belongs_to :customer
belongs_to :carseller
has_one :company, :through => :carseller
end
Then you just have to do appointment.company to get it.

Related

usage of "has_many" vs "has_many, through" relation in rails

i'm new to both rails and web-dev.
currently i'm studding "active record Associations" in rails 4
and i got confused on usage of "has_many" vs "has_many, through" relation.
for example, if i have Physician, Appointment, and Patient model in my schema.(As rails guide provides)
and rails tutorial suggests me to do like this.
class Physician < ApplicationRecord
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ApplicationRecord
belongs_to :physician
belongs_to :patient
end
class Patient < ApplicationRecord
has_many :appointments
has_many :physicians, through: :appointments
end
but what if i make relation like this
class Physician < ApplicationRecord
has_many :appointments
end
class Appointment < ApplicationRecord
belongs_to :physician
has_many :patients
end
class Patient < ApplicationRecord
belongs_to :appointment
end
i think both will work fine.
but i want to know whats the differences and why they made "has_many, through" relations.
thank you for reading my question.
has_many through is a way to join two unrelated, independent models/tables and to reduce duplicates/redundancy in tables, where has_many states more directive relation.
Maybe example with appointments and physicians isn't clear. I'll give a different one.
class Artist
has_many :paintings
has_many :purchases
has_many :buyers, through: :purchases
end
class Painting
belongs_to :artist
end
class Purchase
belongs_to :painting
belongs_to :buyer
end
class Buyer
has_many :paintings_buyers
has_many :painting, through: :purchases
end
Talking about your example.
First, there is no convenient way for you to get physician's patents. The only way is:
physician.appoitments.map(&:patient).uniq
Which will result in
poor performance
inability to filter entities with sql, only with ruby(again poor performance)
Also, did you notice I used uniq? That's because patient's table will have lots of duplicates when the same patients will be appointed multiple times to the same physician.

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.

Rails belongs_to_many

I'm a beginner in Rails and I have a problem with ActiveRecords associations.
I'm creating simple car rental service and I made the following associations:
class Client < ActiveRecord::Base
has_many :rentals
has_many :bookings
has_many :cars, :through => :rentals
has_many :cars, :through => :bookings
end
class Rental < ActiveRecord::Base
belongs_to :client, dependent: :destroy
has_one :car
end
class Booking < ActiveRecord::Base
belongs_to :client, dependent: :destroy
has_one :car
end
What I need is to have a car belonging to many bookings and rentals while every booking and rental can have only one car assigned.
class Car < ActiveRecord::Base
# belongs_to_many :bookings
# belongs_to_many :rentals
end
How should I do that?
If a car can have many bookings/rentals, but a booking/rental can only have one car, you're looking at a classic belongs_to/has_many situation. It looks like you're being tripped up by the distinction between belongs_to and has_one -- it's not a grammatical one, but a matter of where the foreign key column is located in your database.
belongs_to: "I am related to exactly one of these, and I have the foreign key."
has_one: "I am related to exactly one of these, and it has the foreign key."
has_many: "I am related to many of these, and they have the foreign key."
Note that has_one and has_many both imply there's a belongs_to on the other model, since that's the only option where "this" model has the foreign key. Note also that this means has_one should only be used when you have a one-to-one relationship, not a one-to-many.
Taking this into consideration, I would replace the has_one :car with belongs_to :car in both your Rental and Booking models, and place has_many :bookings and has_many :rentals in your Car model. Also ensure that your rentals and bookings tables have a car_id column; there should be no rental- or booking-related columns in your cars table.
Yes, there is a "belongs_to_many" in Rails, sort of. It's a little more work and you can't use generators with it. It's called a polymorphic association.
Even though you could make a car have many bookings & rentals, you could associate the car by making it belong to a polymorph such as rentable_vehicle. Your code would look like this
class Car < ActiveRecord::Base
belongs_to :rentable_vehicle, polymorphic: true
end
class Rental < ActiveRecord::Base
belongs_to :client, dependent: :destroy
has_many :cars, as: :rentable_vehicle
end
class Booking < ActiveRecord::Base
belongs_to :client, dependent: :destroy
has_many :cars, as: :rentable_vehicle
end
You can't do belongs_to_many. The closest you can really get is has_and_belongs_to_many, but I'm not sure that's what you want here - unless you can have multiple cars per rental/booking. Check out the guide for a full explanation.
I'd change it up like this:
class Rental < ActiveRecord::Base
belongs_to :client, dependent: :destroy
belongs_to :car
end
class Booking < ActiveRecord::Base
belongs_to :client, dependent: :destroy
belongs_to :car
end
class Car < ActiveRecord::Base
has_many :bookings
has_many :rentals
end
Also, I don't know how your rentals relate to bookings, but my immediate thought is that there should be some relationship between the two, because you probably can't have a rental without booking it, right?

How would I route this hierarchy

I am creating an app that tracks a users employments and where they are in the companies. I need some help trying to route the app, I has made scaffolds of user, company, and department.
user
company (user has_many :through => employments)
department
user.rb
class User < ActiveRecord::Base
#associations
has_many :employments
has_many :companies, :through => :employments
has_one :department, :through => :employments
end
employment.rb
class Employment < ActiveRecord::Base
belongs_to :user
belongs_to :company
belongs_to :department
has_many :employment_histories
end
employment_history.rb
class EmploymentHistory < ActiveRecord::Base
belongs_to :employment
end
company.rb
class Company < ActiveRecord::Base
has_many :employments
has_many :users, :through => :employments
has_many :departments
end
department.rb
class Department < ActiveRecord::Base
belongs_to :company
end
For routing, the simplest way to do it is to declare your resources as resources, and then you access them through the id of the object.
http://guides.rubyonrails.org/routing.html#resource-routing-the-rails-default
Then to find through associations, I suggest you check out this railscast: http://railscasts.com/episodes/3-find-through-association?view=asciicast
If routing and finding through associations doesn't come easily, you will probably want to refactor your hierarchy to make more sense metaphorically. For instance my approach would be:
User has_many :employments and give it default_scope order: 'employments.created_at DESC' in the User model to make sure the most recent employment is first.
Employment has_one :department
Department belongs_to :company
Company has_many :departments
Then you can access all of this data through associations (see link above). You only need to route the resources, and then know how to access them in the right controllers.

What's the best way to make Rails 3 / Active Record associations for classes of a simple point of sale program?

I have 5 classes that are part of a point of sales program:
Customer, Technician, Order, Ticket, Service
Each Order has one customer and many tickets. Each Ticket has on technician and many services.
How should I make the associations so that I can do the following lookup:
customer.order.find_by_date(10/20/2010).service.technician.name
This is what I am planning:
class Customer < ActiveRecord::Base
has_many :orders
has_many :tickets, :through => :orders
has_many :technicians, :through => :tickets
end
class Technician < ActiveRecord::Base
belongs_to :ticket
belongs_to :service
end
class Service < ActiveRecord::Base
has_many :technicians
belongs_to :ticket
end
class Ticket < ActiveRecord::Base
has_many :services
has_many :technicians, :through => :services
end
class Order < ActiveRecord::Base
has_many :tickets
has_many :services, :through => tickets
has_many :technicians, :through => services
belongs_to :customer
end
The relationship between customer and order is one-to-many. And the relationship between order and service is also one-to-many. Therefore you cannot do:
customer.order.find_by_date('10/20/2010').service.technician.name
It should be:
customer.orders.find_by_date('10/20/2010').services.each do |service|
service.technician.name
end
It's a similar problem as in your other question.

Resources