2009-08-29 4 views
2

Я не новичок в Rails, но до сих пор не делал ничего такого сложного, так что мне интересно, что может сделать более опытный разработчик rails:, когда кювет активная запись?

У меня есть запрос sql, который объединяет 4 или так таблицы в один выход:

SELECT places.id, places.name, places.email, places.website, places.blurb, external_ratings.rating, photos.data_file_name 
    FROM `scannables` 
    INNER JOIN places ON scannables.place_id = places.id 
    INNER JOIN locations ON places.location_id = locations.id 
    LEFT JOIN external_ratings ON scannables.place_id = external_ratings.place_id 
    LEFT JOIN photos ON scannables.place_id = photos.place_id 
    WHERE locations.id = 2474 AND scannables.bookdate BETWEEN '2009-08-29' and date_add('2009-08-29', INTERVAL 4 DAY) 
    GROUP BY scannables.place_id 
    HAVING SUM(scannables.available) >= 4 
    ORDER BY SUM(scannables.available) DESC, external_ratings.rating DESC 

Я все отношения таблиц определены в различных моделях, и первоначально был его вытягивать различные данные только с помощью этих определенных отношений (с использованием активной записи), и она работала хорошо, за исключением на основной запрос, который является самым большим, был нелогичным медленным, выполняя несколько indv. запросы. Мой вопрос в том, должен ли я сбросить Active Record в этом случае и использовать find_by_sql ... или я что-то упустил?

Что такое Rails?

Благодаря

ответ

4

На самом деле я не люблю эти ответы, так что я сделал немного покопаться и повезло ...

Мне это нравится гораздо лучше ....

Place.find(:all, 
     :joins => "INNER JOIN scannables ON scannables.place_id = places.id", 
     :conditions => [ "places.location_id = ? and scannables.bookdate BETWEEN ? and ?", 2474, '2009-08-29', '2009-09-02' ], 
     :group => 'scannables.place_id', 
     :having => 'SUM(scannables.available) >= 4') 

Его гораздо проще, и я могу по-прежнему используйте все хорошие механизмы рельсов, чтобы получить детали, которые мне не нужны явно ... т.е. меньше двух соединений!

Хотя ... мне интересно, есть ли способ упростить его больше? Связь определяется между сканируемыми и местами ... т.е. has_many, принадлежит ... так почему мне все еще нужно указать INNER JOIN ON? не должны

:joins => :scannable work? 

в любом случае .. это не нравится ...

+0

Фактически: наличие не имеет надлежащего эффекта ... по крайней мере, не такой же эффект, как исходный sql выше ... i также используется a: order => 'sum (scannables.availables)', который не работает должным образом ... ;-( – holden

11

Это более важно, чтобы быть прагматичным, чем беспокоиться о сохранении «чистоты Rails». Мне нравятся названные области, ассоциации и вся магия, которая идет с ними. Конечно, я предпочитаю, чтобы выполнялся необработанный SQL-запрос. Однако, если сложный запрос вызывает find_by_sql, я буду использовать его, не теряя сна.

Если вам необходимо поддерживать несколько баз данных, вам может потребоваться перевести это в чистый подход Rails, но это требование встречается довольно редко.

+0

Слушайте, слышите! 'find_by_sql' существует по какой-то причине. –

+0

Я забочусь о чистоте рельсов только в том случае, если он лучше служит моему приложению! вот почему я думал, что это может быть излишним ... – holden

+0

и мое собственное рассудительность конечно – holden

0

Возможно, вы захотите рассмотреть вопрос об использовании sequel, если у вас есть несколько таких запросов. В противном случае я согласен с jdl.

2

Использование

:joins => :scannables 

должен работать (обратите внимание на множественное число), если вы создали Place # has_many: ассоциация scannables. Параметр: joins для #find принимает как строки, так и именованные ассоциации.

+0

В чем большая разница между: join и: включает? – holden

+0

: include позволяет указать ассоциации, которые должны быть загруженным.: joins позволяет указать способ, с которым происходят ваши соединения. – jdl

Смежные вопросы