Reputation: 5765
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
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
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
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 nil
s:
def all_listings
[car, truck, bike].compact
end
Upvotes: 1