La mia ipotesi è che i tuoi modelli abbiano questo aspetto:
class User < ActiveRecord::Base
has_many :reviews
end
class Review < ActiveRecord::Base
belongs_to :user
belongs_to :reviewable, polymorphic: true
end
class Shop < ActiveRecord::Base
has_many :reviews, as: :reviewable
end
Non sei in grado di eseguire quella query per diversi motivi.
- ActiveRecord non è in grado di creare il join senza ulteriori informazioni.
- Non esiste una tabella denominata revisionabile
Per risolvere questo problema, è necessario definire in modo esplicito la relazione tra Review
e Shop
.
class Review < ActiveRecord::Base
belongs_to :user
belongs_to :reviewable, polymorphic: true
# For Rails < 4
belongs_to :shop, foreign_key: 'reviewable_id', conditions: "reviews.reviewable_type = 'Shop'"
# For Rails >= 4
belongs_to :shop, -> { where(reviews: {reviewable_type: 'Shop'}) }, foreign_key: 'reviewable_id'
# Ensure review.shop returns nil unless review.reviewable_type == "Shop"
def shop
return unless reviewable_type == "Shop"
super
end
end
Quindi puoi eseguire una query in questo modo:
Review.includes(:shop).where(shops: {shop_type: 'cafe'})
Notare che il nome della tabella è shops
e non reviewable
. Non dovrebbe esserci una tabella chiamata revisionabile nel database.
Credo che questo sia più facile e più flessibile rispetto alla definizione esplicita del join
tra Review
e Shop
poiché consente di caricare con entusiasmo oltre a eseguire query per campi correlati.
Il motivo per cui ciò è necessario è che ActiveRecord non può creare un join basato sul solo revisionabile, poiché più tabelle rappresentano l'altra estremità del join e SQL, per quanto ne so, non ti consente di unirti a una tabella denominata dal valore memorizzato in una colonna. Definendo la relazione extra belongs_to :shop
, si forniscono ad ActiveRecord le informazioni necessarie per completare il join.
@reviews = @user.reviews.joins("INNER JOIN shops ON (reviewable_type = 'Shop' AND shops.id = reviewable_id AND shops.shop_type = '" + type + "')").includes(:user, :reviewable => :photos)