Мне было интересно, есть ли способ использовать find_by_sql в named_scope. Я хотел бы рассматривать пользовательский sql как named_scope, чтобы я мог связать его с моими существующими named_scopes. Это также было бы хорошо для оптимизации часто используемого фрагмента sql.


конечно, почему бы и нет
: named_scope: conditions => [ваш 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 - если у вас их несколько, они объединяются с помощью AND)
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, необходимо знать, как они сочетаются друг с другом.
Когда вы создаете обычные запросы, все select, joins, conditions и т. д. Разбиваются на отдельные части. Rails знает, что может добавлять элементы к условиям, не затрагивая все остальное (так работают with_scope и named_scope).
Однако с find_by_sql вы просто дадите рельсам большую веревку. Он не знает, что куда идет, поэтому ему небезопасно входить и добавлять то, что ему нужно добавить, чтобы области работали.
Это не совсем то, о чем вы спрашивали, но вы можете исследовать 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'"
}