DEV Community

Aleksandr Korolev
Aleksandr Korolev

Posted on

Rails: has_many relationships by two columns

You probably use has_many relationships very often. This stuff is very useful and helps to reflect a lot of relationships from the real world. For example, a car has many parts:

class Car < ApplicationRecord
  has_many :parts
end
Enter fullscreen mode Exit fullscreen mode

On database level, the Parts table should have a link to the Car table, usually some sort of foreign key ( car_id column in the Parts table).

But what if you need to create a has_many relationship by two columns?

Let's imagine that we have next: except Car, there are next models:

class Inventory < ApplicationRecord
  # it stores all possible parts that we can use for your cars
end

class CarInventory < ApplicationRecord
  # join model
  belongs_to :car
  belongs_to :inventory
end

class Analogs < ApplicationRecord
  belongs_to :car
  belongs_to :inventory
  has_many :inventories
end
Enter fullscreen mode Exit fullscreen mode

Our task is to be able to get all analogs for a specific detail.
The simplest way is just to add a link to the CarInventory in Analog model - create a database migration and probably data migration).
But we use pure SQL we can fetch required data without any changes:

SELECT *
FROM Analogs as an
JOIN CarInventory as ci on ci.inventory_id = an.inventory_id and ci.car_id = an.car_id
WHERE ci.car = <car_id> and ci.inventory_id = <inv_id> and ci.id = <car_inventory.id>
Enter fullscreen mode Exit fullscreen mode

In order to achieve this we can write the next code:

# in CarInventory model
has_many :analogs, ->(car_inventory) do
    Analog.where(car: car_inventory.car, inventory: car_inventory.inventory)
  end, through: :Inventory
Enter fullscreen mode Exit fullscreen mode

The example probably doesn't reflect real life but I hope can reveal the idea.

Top comments (0)