Tahminim, modellerin şöyle görünüyor:
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
Bu sorguyu birkaç nedenden dolayı yapamazsınız.
- ActiveRecord, ek bilgi olmadan birleştirme oluşturamaz.
- İncelenebilir diye bir tablo yok
Bu sorunu çözmek için, Review
ve arasındaki ilişkiyi açıkça tanımlamanız gerekir 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
Sonra şu şekilde sorgulayabilirsiniz:
Review.includes(:shop).where(shops: {shop_type: 'cafe'})
Tablo adının olduğuna shops
ve olmadığına dikkat edin reviewable
. Veritabanında incelenebilir diye bir tablo olmamalıdır.
Bunu daha kolay ve açıkça tanımlamak yerine daha esnek olduğuna inandığımız join
arasında Review
ve Shop
bunun ilgili alanlara göre sorgulama ek olarak istekli yüke olanak sağlar çünkü.
Bunun gerekli olmasının nedeni, ActiveRecord'un tek başına gözden geçirilebilirliğe dayalı bir birleştirme oluşturamamasıdır, çünkü birden çok tablo birleştirmenin diğer ucunu temsil eder ve bildiğim kadarıyla SQL, depolanan değere göre adlandırılan bir tabloya katılmanıza izin vermez. bir sütunda. Ekstra ilişkiyi tanımlayarak, belongs_to :shop
ActiveRecord'a birleştirme işlemini tamamlamak için ihtiyaç duyduğu bilgileri veriyorsunuz.
@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)