Dugaan saya adalah model Anda terlihat seperti ini:
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
Anda tidak dapat melakukan kueri itu karena beberapa alasan.
- ActiveRecord tidak dapat membuat gabungan tanpa informasi tambahan.
- Tidak ada tabel yang disebut dapat ditinjau
Untuk mengatasi masalah ini, Anda perlu secara eksplisit menentukan hubungan antara Review
dan 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
Kemudian Anda dapat melakukan kueri seperti ini:
Review.includes(:shop).where(shops: {shop_type: 'cafe'})
Perhatikan bahwa nama tabel adalah shops
dan bukan reviewable
. Seharusnya tidak ada tabel yang disebut dapat ditinjau dalam database.
Saya percaya ini akan lebih mudah dan lebih fleksibel daripada secara eksplisit mendefinisikan join
antara Review
dan Shop
karena memungkinkan Anda untuk memuat dengan bersemangat sebagai tambahan untuk membuat kueri berdasarkan bidang terkait.
Alasan mengapa hal ini diperlukan adalah karena ActiveRecord tidak dapat membuat gabungan berdasarkan dapat ditinjau saja, karena beberapa tabel mewakili ujung gabungan lainnya, dan SQL, sejauh yang saya tahu, tidak mengizinkan Anda bergabung dengan tabel yang diberi nama berdasarkan nilai yang disimpan di kolom. Dengan menentukan hubungan ekstra belongs_to :shop
, Anda memberikan informasi yang dibutuhkan ActiveRecord untuk menyelesaikan penggabungan.
@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)