Когда у меня сложный SQL-запрос, включающий много объединений, UNION и т. Д., Я создаю представление в mysql. Затем я создаю модель ActiveRecord и могу напрямую читать результаты через ActiveRecord.
Еще одним преимуществом этого метода является то, что сложный SQL и его план выполнения будут рассчитываться только один раз в дБмс (при создании представления), а не при каждом выполнении.
В зависимости от ситуации, я использую грабли или миграцию для создания / повторного создания представлений.
Обратите внимание, что вы обычно захотите воссоздать представления, если какая-либо из схем базовых таблиц будет изменена.
Добавлено:
Пример
class SessionViews2 < ActiveRecord::Migration
def self.up
execute "DROP View if exists room_usages" # Dropping both view and table
execute "DROP Table if exists room_usages" # has helped in some corner cases
execute "CREATE VIEW room_usages AS
SELECT
CONCAT(rooms.id,schedules.id) as id
, rooms.id as room_id
, rooms.conference_id as conference_id
, rooms.popular_room as room_popular_room
, schedules.id as schedule_id
, schedules.timetable_id as schedule_timetable_id
, schedules.display_start_time as schedule_display_start_time
, schedules.display_end_time as schedule_display_end_time
, sess.id as session_id
, sess.title as title
, sess.subtitle as subtitle
FROM
rooms
INNER JOIN schedule_rooms ON rooms.id = schedule_rooms.room_id
INNER JOIN schedules ON schedule_rooms.schedule_id = schedules.id
INNER JOIN sessions as sess ON schedules.session_id = sess.id
WHERE
schedule_rooms.cancelled_time IS NULL
AND schedules.cancelled_time IS NULL"
end
def self.down
execute "DROP View if exists room_usages"
execute "DROP Table if exists room_usages"
end
end
Модель room_usage.rb
class RoomUsage < ActiveRecord::Base
############################################################
# #
# This is a VIEW! No DB table, Read-Only #
# #
############################################################
belongs_to :conference
belongs_to :timetable, :foreign_key => :schedule_timetable_id
belongs_to :session
end