Ich vermute, dass Ihre Modelle so aussehen:
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
Sie können diese Abfrage aus mehreren Gründen nicht ausführen.
- ActiveRecord kann den Join ohne zusätzliche Informationen nicht erstellen.
- Es gibt keine Tabelle mit der Bezeichnung "überprüfbar"
Um dieses Problem zu lösen, müssen Sie die Beziehung zwischen Review
und explizit definieren 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
Dann können Sie wie folgt abfragen:
Review.includes(:shop).where(shops: {shop_type: 'cafe'})
Beachten Sie, dass der Tabellenname lautet shops
und nicht reviewable
. In der Datenbank sollte keine Tabelle mit dem Namen überprüfbar vorhanden sein.
Ich glaube, dies ist einfacher und flexibler als das explizite Definieren des join
Dazwischen Review
und Shop
da es Ihnen ermöglicht, zusätzlich zum Abfragen nach verwandten Feldern eifrig zu laden.
Der Grund dafür ist, dass ActiveRecord keinen Join erstellen kann, der nur auf überprüfbar basiert, da mehrere Tabellen das andere Ende des Joins darstellen und SQL meines Wissens nicht zulässt, dass Sie einer Tabelle beitreten, die nach dem gespeicherten Wert benannt ist in einer Spalte. Indem Sie die zusätzliche Beziehung definieren belongs_to :shop
, geben Sie ActiveRecord die Informationen, die zum Abschließen des Joins erforderlich sind.
@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)