named_scopeでのSQLのカプセル化
-
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文字列をそのまま保持します-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レールを構築するには、SQLレールがどのように適合するかを知る必要があります。
通常のクエリを作成すると、 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:conditions => [あなたのSQL]