Supongo que sus modelos se ven así:
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
No puede realizar esa consulta por varias razones.
- ActiveRecord no puede generar la combinación sin información adicional.
- No hay una tabla llamada revisable
Para resolver este problema, debe definir explícitamente la relación entre Review
y 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
Entonces puedes consultar así:
Review.includes(:shop).where(shops: {shop_type: 'cafe'})
Observe que el nombre de la tabla es shops
y no reviewable
. No debería haber una tabla denominada revisable en la base de datos.
Creo que esto es más fácil y más flexible que definir explícitamente el join
intermedio Review
y, Shop
ya que le permite realizar una carga ansiosa además de realizar consultas por campos relacionados.
La razón por la que esto es necesario es que ActiveRecord no puede construir una combinación basada en solo revisable, ya que varias tablas representan el otro extremo de la combinación, y SQL, hasta donde yo sé, no le permite unirse a una tabla nombrada por el valor almacenado en una columna. Al definir la relación adicional belongs_to :shop
, le está dando a ActiveRecord la información que necesita para completar la unión.
@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)