Home > Back-end >  Rails architecture issue
Rails architecture issue

Time:04-23

I have an app where I have a list of Cars. I have a form above that can filter them based on different attributes. I wish to add filtering based on their model and sub-models.

Each car already has a Manufacturer and these have models and then sub-models.

How can I structure this in Rails? Do I have a Modell and a SubModell (using those names to stop conflicting with rails own naming). or is there a better way?

I wish to be able to return the Manufacturer and Model and Sub Model directly from a car though. Like so:

c = Car.first
c.manufacturer # => "Ford"
c.model # => "Mondeo"
c.sub_model # => "Estate"

Is this possible?

Neil, Thanks in advance

CodePudding user response:

Yes, you can do this, the convention would be...

class VehicleManufacturer
  has_many vehicle_models
end

class VehicleModel
  has_many vehicle_sub_models
  belongs_to :vehicle_manufacturer
end

class VehicleSubModel
  belongs_to :vehicle_model
  has_many :vehicles
   delegate :vehicle_manufacturer, to: :vehicle_model
end

class Car
  belongs_to vehicle_sub_model
  delegate :vehicle_model, :vehicle_manufacturer, to: :vehicle_sub_model
  delegate :name, to: :vehicle_manufacturer, prefix: true
  delegate :name, to: :vehicle_model, prefix: true
  delegate :name, to: :vehicle_sub_model, prefix: true
end

This will let you do...

c = Car.first
c.vehicle_manufacturer_name # => "Ford"
c.vehicle_model_name # => "Mondeo"
c.vehicle_sub_model_name # => "Estate"

You would only need to assign the correct vehicle_sub_model to the car and the other classes would automatically be available.

In your case, you already have a vehicle_manufacturer association in the car model, so you don't need the delegation to vehicle_manufacturer in the model, but you would still need to assign the vehicle_sub_model to the car (otherwise you won't know what model / sub_model the car is)

CodePudding user response:

Here is my solution, very close to what Steve has proposed:

With this solution, a car might have several manufacturers without having a sub model linked (optional: true)

class VehicleManufacturer
  has_many :vehicle_models
  has_many :car_vehicle_manufacturers
  has_many :cars, through: :car_vehicle_manufacturers
end

class VehicleModel
  has_many :vehicle_sub_models
end

class VehicleSubModel
  belongs_to :vehicle_model
end

class Car
  # Limitation here, in case there is a "sub-sub-model" or if there is no "sub-model" but directly a model. 
  belongs_to :vehicle_sub_model, optional: true
  has_many :car_vehicle_manufacturers
  has_many :vehicle_manufacturers, through: :car_vehicle_manufacturers
  
  # Pay attention to the eager loading with delegation, it won't work. 
  delegate :vehicle_model, :vehicle_manufacturer, to: :vehicle_sub_model
  delegate :name, to: :vehicle_model, prefix: true
  delegate :name, to: :vehicle_sub_model, prefix: true
end
  • Related