user2012677
user2012677

Reputation: 5765

Define has_many through relationship across several models

Given these model relationships, how can I retrieve all Users listings, which are related through, Truck, Car, Bike, etc.

#MODELS

class Car < ApplicationRecord
  belongs_to :user

  has_one  :listing, as: :listable
  has_one  :firm, as: :firmable
  has_one  :seller, as: :sellable
end

class Car < ApplicationRecord
  belongs_to :user

  has_one  :listing, as: :listable
  has_one  :firm, as: :firmable
  has_one  :seller, as: :sellable
end

class Bike < ApplicationRecord
  belongs_to :user

  has_one  :listing, as: :listable
  has_one  :firm, as: :firmable
  has_one  :seller, as: :sellable
end

class Listing < ApplicationRecord
  belongs_to :listable, polymorphic: true
end

class User < ApplicationRecord
  has_one :car, dependent: :destroy
  has_one :truck, dependent: :destroy
  has_one :bike, dependent: :destroy

  # need method to retrieve all the listings, which are associated through several models, Car, Truck, Bike, etc.

end

Upvotes: 0

Views: 36

Answers (3)

Ashok Damaniya
Ashok Damaniya

Reputation: 303

i suggest you should try dry concept and use Concern

module Vehical
  extend ActiveSupport::Concern

  included do
    has one :car, dependent: :destroy
    has_one :truck, dependent: :destroy
    has_one :bike, dependent: :destroy
  end

  def list_vehicals
   [
     car, 
     truck,
     bike
   ]
  end 
end

Then include concern in your User model

class User < ApplicationRecord
  include Vehical
end

then you can use it like

@user = User.find(user_id) 
@user.list_vehicals

Upvotes: 0

arieljuod
arieljuod

Reputation: 15848

I guess you can do something like:

Listing.where(listable: car).or(Listing.where(listable: bike)).or(Listing.where(listable: truck))

It looks ugly and it requires 4 queries in total, but I don't think you can make that better with your models.

Maybe you could make Listing belong to User too, not sure if you can do that though, but looks cleaner to me.

Also, you say you have "several models" that, from your code, looks too similar. That looks weird, maybe you can improve that design and have a cleaner query.

Upvotes: 0

Aaron Breckenridge
Aaron Breckenridge

Reputation: 1819

Have you considered adding a method to the User model that does what you want?

class User
  has one :car, dependent: :destroy
  has_one :truck, dependent: :destroy
  has_one :bike, dependent: :destroy

  def all_listings
    [car, truck, bike]
  end
end

And maybe throw on a compact to discard nils:

def all_listings
  [car, truck, bike].compact
end

Upvotes: 1

Related Questions