我试图通过:through和:source选项使用两个相似的多态关联来进行SQL搜索。我看到的是,rails正在为第一个“has_many:reservation_trip_itinerary_entries ......”遗漏一个表名别名。
奖金问题:是否可以创建一个新的关联或别名,它将返回一个关联,但如果一个为空,则还原为备份?也许这值得另一个问题?
这是行程条目(通过TripType和分支ReservationTrip预订的子项,每个包含一个单独的列表):
class ItineraryEntry < ActiveRecord::Base
default_scope order('position ASC')
attr_accessible :title, :code, :datetime, :position, :itinerary_type, :itinerary_id, :action_type, :action_id
belongs_to :itinerary, polymorphic: true
belongs_to :action, polymorphic: true
这是预订(许多ItineraryEntries的父级):
class Reservation < ActiveRecord::Base
has_many :reservation_trips, :order => :departure_date, :dependent => :destroy
has_many :trip_types, :through => :reservation_trips # contact booking report
has_many :reservation_trip_itinerary_entries, :through => :reservation_trips, :source => :itinerary_entries
has_many :trip_type_itinerary_entries, :through => :trip_types, :source => :itinerary_entries
# excluded irrelevant methods
def search
# many other search params excluded, all populating 'includes' and
# 'warez' in the same way
if params.key?(:itinerary_entry) and not params[:itinerary_entry].empty?
includes.push(:reservation_trip_itinerary_entries)
includes.push(:trip_type_itinerary_entries)
warez.push("(
(reservation_trip_itinerary_entries.action_type = '#{params[:itinerary_entry][:action_type]}' AND
reservation_trip_itinerary_entries.action_id = #{params[:itinerary_entry][:action_id]})
OR
(trip_type_itinerary_entries.action_type = '#{params[:itinerary_entry][:action_type]}' AND
trip_type_itinerary_entries.action_id = #{params[:itinerary_entry][:action_id]})
)")
end
Reservation.includes(includes).where(warez.join(' AND ')).order('reservations.created_at DESC').limit(params[:limit])
end
这是它正在生成的sql,带有错误。请注意第一个“itinerary_entries”列表如何在第二个列表中没有别名(“trip_type_itinerary_entries_reservations”):
SELECT DISTINCT "reservations".id,
reservations.created_at AS alias_0
FROM "reservations"
LEFT OUTER JOIN "reservation_trips" ON "reservation_trips"."reservation_id" = "reservations"."id"
LEFT OUTER JOIN "itinerary_entries" ON "itinerary_entries"."itinerary_id" = "reservation_trips"."id"
AND "itinerary_entries"."itinerary_type" = 'ReservationTrip'
LEFT OUTER JOIN "reservation_trips" "reservation_trips_reservations_join" ON "reservation_trips_reservations_join"."reservation_id" = "reservations"."id"
LEFT OUTER JOIN "trip_types" ON "trip_types"."id" = "reservation_trips_reservations_join"."trip_type_id"
LEFT OUTER JOIN "itinerary_entries" "trip_type_itinerary_entries_reservations" ON "trip_type_itinerary_entries_reservations"."itinerary_id" = "trip_types"."id"
AND "trip_type_itinerary_entries_reservations"."itinerary_type" = 'TripType'
WHERE (( (reservation_trip_itinerary_entries.action_type = 'Activity'
AND reservation_trip_itinerary_entries.action_id = 3)
OR (trip_type_itinerary_entries.action_type = 'Activity'
AND trip_type_itinerary_entries.action_id = 3) ))
ORDER BY reservations.created_at DESC LIMIT 100
这是SQL错误:
PG::Error: ERROR: missing FROM-clause entry for table "reservation_trip_itinerary_entries"
LINE 2: (reservation_trip_itinerary_entries.action_type = ...
^
思考?谢谢!
答案 0 :(得分:0)
玩完这个之后,我发现ActiveRecord在这里有一个细微差别。它不会为第一个关联指定别名(在原始问题中命名为“itinerary_entries”),但会为所有后续关联指定别名。
所以我通过黑客攻击我的WHERE子句得到了我的查询,如下所示:
if params.key?(:itinerary_entry) and not params[:itinerary_entry].empty?
includes.push(trip_types: [:itinerary_entries], reservation_trips: [:itinerary_entries])
warez.push("
(itinerary_entries.action_type = '#{params[:itinerary_entry][:action_type]}' AND
itinerary_entries.action_id = #{params[:itinerary_entry][:action_id]}) OR
(itinerary_entries_trip_types.action_type = '#{params[:itinerary_entry][:action_type]}' AND
itinerary_entries_trip_types.action_id = #{params[:itinerary_entry][:action_id]})
")
end
哪个产生了这个查询
SELECT DISTINCT "reservations".id,
reservations.created_at AS alias_0
FROM "reservations"
LEFT OUTER JOIN "reservation_trips"
ON "reservation_trips"."reservation_id" =
"reservations"."id"
LEFT OUTER JOIN "itinerary_entries"
ON "itinerary_entries"."itinerary_id" =
"reservation_trips"."id"
AND "itinerary_entries"."itinerary_type" =
'ReservationTrip'
LEFT OUTER JOIN "reservation_trips" "reservation_trips_reservations_join"
ON "reservation_trips_reservations_join"."reservation_id" =
"reservations"."id"
LEFT OUTER JOIN "trip_types"
ON "trip_types"."id" =
"reservation_trips_reservations_join"."trip_type_id"
LEFT OUTER JOIN "itinerary_entries" "itinerary_entries_trip_types"
ON "itinerary_entries_trip_types"."itinerary_id" =
"trip_types"."id"
AND "itinerary_entries_trip_types"."itinerary_type" =
'TripType'
WHERE ( ( itinerary_entries.action_type = 'Activity'
AND itinerary_entries.action_id = 3 )
OR ( itinerary_entries_trip_types.action_type = 'Activity'
AND itinerary_entries_trip_types.action_id = 3 ) )
ORDER BY reservations.created_at DESC
LIMIT 100