質問
アレルとキーキーに頭を悩ませようとしていますが、探しているものを Google に尋ねる語彙が不足しているように感じます。
TL;DR: 合成オブジェクトからSqueel のModel.where{related.objects.field.matches string}
構文を模倣する方法を知っている人はいますか?Squeel::Node
問題
この質問は、次のように、文字列から Squeel KeyPath を構築する方法を示しています。
search_relation = 'person.pets'
User.joins{Squeel::Nodes::KeyPath.new(search_relation.split('.'))}
# Mimics User.joins{person.pets}
この記事では、複数の列にまたがる検索をメタプログラミングする方法を学びました。文書化された Squeel トリック(ページの最後の行) でクリーンアップすると、次のようになります。
search_columns = %w[first_name last_name]
search_term = 'chris'
User.where{
search_columns.map do |column|
column_stub = Squeel::Nodes::Stub.new(column)
Squeel::Nodes::Predicate.new(column_stub, :matches, "%#{search_term}%")
end.compact.inject(&:|)
}
# Mimics User.where{(last_name.matches '%chris%') | (first_name.matches '%chris%')}
私が望むのは、次の構文を模倣して、2つを組み合わせることができることです
User.joins{person.pets}.where{person.pets.name.matches '%polly%'}
squeel オブジェクトを自分で作成することによって。
最初の部分は簡単で、最初の例で示されています。クエリ対象のテーブルの列に対して直接実行できる 2 番目の部分は、2 番目の例で示されています。
ただし、テーブルに結合された列の 2 番目の部分を実行する方法がわかりません。KeyPath
2 番目の例でオブジェクトのスコープを設定するには、最初の例のオブジェクトを使用する必要があると思いますPredicate
。オブジェクトは、単一のテーブルの単一の列を表すPredicate
オブジェクトでのみ機能するようです。Stub
KeyPath
以前の試み
仮定
search_relation = 'key.path'
search_column = 'field'
search_term = '%search%'
keypath = Squeel::Nodes::KeyPath.new(search_relation.split('.') << search_column)
matches
KeyPath でメソッドを呼び出してみました。
Model.where{keypath.matches search_term}
#=> NoMethodError: undefined method `matches' for Squeel::Nodes::KeyPath
一致演算子を使用してみました=~
:
Model.where{keypath =~ search_term}
#=> TypeError: type mismatch: String given
そして、パラメータPredicate
を渡して手動でビルドしようとしました::matches
Model.where{Squeel::Nodes::Predicate.new(keypath, :matches, search_term)}
#=> ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column
#=> 'model.key.path.field' in 'where clause':
#=> SELECT `model`.* FROM `model`
#=> INNER JOIN `key` ON `key`.`id` = `model`.`key_id`
#=> INNER JOIN `path` ON `path`.`id` = `key`.`path_id`
#=> WHERE `model`.`key.path.field` LIKE '%search%'
ここでは、SQL を正常に生成し (上記のように正しく結合し、読みやすくするために省略しています)、それをトラバースするのではなく、フィールドであるModel.joins{search_relation}
と想定します。KeyPath