Я думаю, що ваші моделі виглядають так:
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
Ви не можете виконати цей запит з кількох причин.
- ActiveRecord не може побудувати з'єднання без додаткової інформації.
- Таблиці, яка називається оглядовою, не існує
Щоб вирішити це питання, потрібно чітко визначити зв’язок між Review
та 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
Тоді ви можете зробити такий запит:
Review.includes(:shop).where(shops: {shop_type: 'cafe'})
Зауважте, що назва таблиці є shops
і ні reviewable
. У базі даних не повинно бути таблиці, яка називається переглядається.
Я вважаю, що це простіше і гнучкіше, ніж чітко визначати join
між ними, Review
і Shop
оскільки це дозволяє прагнути завантаження на додаток до запитів за відповідними полями.
Причина, що це необхідно, полягає в тому, що ActiveRecord не може побудувати приєднання на основі лише огляду, оскільки кілька таблиць являють собою інший кінець з'єднання, а SQL, наскільки я знаю, не дозволяє приєднатись до таблиці, названої значенням, що зберігається у стовпчик. Визначаючи додаткові відносини belongs_to :shop
, ви надаєте ActiveRecord інформацію, необхідну для завершення з'єднання.
@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)