Инкапсуляция SQL в named_scope
-
02-07-2019 - |
Вопрос
Мне было интересно, есть ли способ использовать "find_by_sql" в named_scope.Я бы хотел рассматривать пользовательский sql как named_scope, чтобы я мог привязать его к моим существующим named_scopes.Это также было бы полезно для оптимизации фрагмента sql, который я часто использую.
Решение
Хотя вы можете поместить любой SQL, который вам нравится, в условия именованной области, если вы затем вызовете find_by_sql
затем "области видимости" выбрасываются.
Данный:
class Item
# Anything you can put in an sql WHERE you can put here
named_scope :mine, :conditions=>'user_id = 12345 and IS_A_NINJA() = 1'
end
Это работает (он просто вставляет туда строку SQL - если у вас есть более одной, с которой они соединяются, И)
Item.mine.find :all
=> SELECT * FROM items WHERE ('user_id' = 887 and IS_A_NINJA() = 1)
Однако это не означает, что
Items.mine.find_by_sql 'select * from items limit 1'
=> select * from items limit 1
Итак, ответ - "Нет".Если вы подумаете о том, что должно происходить за кулисами, то в этом есть большой смысл.Для того чтобы собрать SQL rails, необходимо знать, как это сочетается друг с другом.
Когда вы создаете обычные запросы, select
, joins
, conditions
, и т.д. Все они разбиты на отдельные части.Rails знает, что он может добавлять что-то к условиям, не влияя на все остальное (вот как with_scope
и named_scope
работа).
С find_by_sql
однако вы просто даете rails большую строку.Он не знает, что куда идет, поэтому для него небезопасно входить и добавлять то, что ему нужно добавить, чтобы области работали.
Другие советы
Это не совсем то, о чем вы спрашивали, но вы могли бы исследовать 'contruct_finder_sql'.Это позволяет вам получить SQL именованной области.
named_scope :mine, :conditions=>'user_id = 12345 and IS_A_NINJA() = 1'
named_scope :additional {
:condtions => mine.send(:construct_finder_sql,{}) + " additional = 'foo'"
}
конечно, почему бы и нет
:named_scope :условия => [ ваш sql]