rails association has many with multiple models - ruby-on-rails

class City < ApplicationRecord
has_many :hospitals
has_many :employees
end
class Hospital < ApplicationRecord
belongs_to :city
has_many :employees
end
class Employee < ApplicationRecord
belongs_to :hospital
belongs_to :city
end
These are my models. Is there any way to get employees for hospital where the hospital located without passing #city parameter in Hospital model.
hospital.rb
has_many :employees, ->(hospital_city) { where(city: hospital_city) }
This works fine. but I need to pass the hospital_city everytime. I want something like this.
has_many :employees, -> { #do something and return employees belongs to hospital & hospital city. }
through not works since employee table has city_id, hospital_id

You could just define a method on Hospital.
class Hospital < ApplicationRecord
belongs_to :city
has_many :employees
def employees_in_city
employees.where(city: city)
end
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.

has_many and has_many relation

I have Country, City, Shop models
class Country < ActiveRecord::Base
has_many :cities
end
class City < ActiveRecord::Base
belongs_to :country
has_many :shops
end
class Shop < ActiveRecord::Base
belongs_to :city
end
How can I get country.shops in activerecord? (get all shops in country)
I usually use Country.cities.collect { |c| c.shops }
but this is not activerecord object.
I have considered add country_id on shop model and set has_many relation but I think it's not best way.
In Country, add a has_many :through relation:
class Country < ActiveRecord::Base
has_many :cities
has_many :shops, through: :cities
end
Now you can write country.shops and receive an appropriate ActiveRecord relation where you can say stuff like country.shops.where name:"Nieman Marcus" and other such queries.
you can def a method in Class Country
def all_shops
self.cities.collect { |c| c.shops }
end
you alse can use Mongoid::Tree
def all_shops
Shop.where(:parent_ids => self.id)
end

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

complex query... how to join many classes in rails?

I have the following associations:
class Venue < ActiveRecord::Base
has_many :sales
end
class Sale < ActiveRecord::Base
has_many :sale_lines
has_many :beverages, through: :sale_lines
end
class SaleLine < ActiveRecord::Base
belongs_to :sale
belongs_to :beverage
end
class Beverage < ActiveRecord::Base
has_many :sale_lines
has_many :sales, through: :sale_lines
has_many :recipes
has_many :products, through: :recipes
end
class Recipe < ActiveRecord::Base
belongs_to :beverage
belongs_to :product
end
class Product < ActiveRecord::Base
has_many :recipes
has_many :beverages, through: :recipes
end
I wan't to see the quantity of products sold by each venue, so basically I have to multiply the recipe.quantity by the sale_line.quantity of an specific product.
I would like to call #venue.calc_sales(product) to get the quantity sold of product.
Inside the class Venue I am trying to calculating it by:
class Venue < ActiveRecord::Base
has_many :sales
def calc_sales(product)
sales.joins(:sale_lines, :beverages, :recipes).where('recipes.product_id = ?', product.id).sum('sale_lines.quantity * recipe.quantity')
end
end
However, I can't access the recipes in that way.
Any idea on how to achieve it?
For the joins, you have to use a Hash to join a already-joined table. It's hard to explain, but here are some examples:
Venue.joins(:sales, :beverages) : This implies that the relations :sales and :beverages are declared on the Venue model.
Venue.joins(:sales => :beverages) : This implies that the relation :sales exists on the Venue model, and the relation :beverages exists on the Sale model.
Consider this:
Venue
has_one :sale
Venue.joins(:sales) : This would not work, you have to use the exact same name as the relation between the Venue model & Sale model.
Venue.joins(:sale) : This would work because you used the same name of the relation.
Attention: You have to use the pluralized name in the where clause:
Venue.joins(:sale).where(:sales => { :id => sale.id })
^^ ^^ # See the plural
In your case, you can do something like this:
sales.joins(:sale_lines => { :beverage => :recipes })
.where(:recipes => { :product_id => product.id })
.sum('sale_lines.quantity * recipes.quantity')

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