2

質問

アレルとキーキーに頭を悩ませようとしていますが、探しているものを 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 番目の部分を実行する方法がわかりません。KeyPath2 番目の例でオブジェクトのスコープを設定するには、最初の例のオブジェクトを使用する必要があると思いますPredicate。オブジェクトは、単一のテーブルの単一の列を表すPredicateオブジェクトでのみ機能するようです。StubKeyPath

以前の試み

仮定

search_relation = 'key.path'
search_column = 'field'
search_term = '%search%'
keypath = Squeel::Nodes::KeyPath.new(search_relation.split('.') << search_column)

matchesKeyPath でメソッドを呼び出してみました。

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

4

2 に答える 2

2

クリス、

あなたは正しい軌道に乗っています。KeyPath オブジェクトで matches メソッドを呼び出すだけで、左側にキーパス、右側に match への引数を含む、matches 述語が作成されます。Squeel の訪問者は、左側のキーパスをたどり、問題の属性に到達し、それに対して一致する ARel 述語を作成します。

于 2012-11-27T13:19:10.157 に答える
1

最初のKeyPath例の はテーブルを結合するのに十分ですが、句KeyPathで使用されるWHEREa は、最後の値が実際に a であることを確認することにより、もう少し慎重に構築する必要がありますStub

search_relation = 'key.path'
search_column = 'field'
search_stub = Squeel::Nodes::Stub(search_column)
search_term = '%search%'
keypath = Squeel::Nodes::KeyPath.new(search_relation.split('.') << search_stub)

Model.where{Squeel::Nodes::Predicate.new(keypath, :matches, search_term)}
#=> SELECT `model`.* FROM `model`
#=>   INNER JOIN `key` ON `key`.`id` = `model`.`key_id`
#=>   INNER JOIN `path` ON `path`.`id` = `key`.`path_id`
#=>   WHERE `path`.`field` LIKE '%search%'
于 2012-11-27T18:06:28.510 に答える