Rails 5:ActiveRecord ORクエリ


回答:


228

クエリorwhere句と一緒に句をチェーンする機能ActiveRecordは、Rails 5で利用できるようになります。参照関連する議論とプル要求を

したがって、Rails 5では次のことができるようになります。

1または2 postでを取得するにはid

Post.where('id = 1').or(Post.where('id = 2'))

その他の例:

(A && B)|| C:

    Post.where(a).where(b).or(Post.where(c))

(A || B)&& C:

    Post.where(a).or(Post.where(b)).where(c)

3
(A || B)&&(C || D)を取得するにはどうすればよいですか。Post.where(a).or(Post.where(b))。where(c).or(Post.where(d))を試しましたが、次のように生成されます:(A || B)&& C || D
イムランアフマド

3
@Imran私はこれがPost.where(a).or(Post.where(b)).where(Post.where(c).or(Post.where(d)))(a || b)&&(c || d)を作成するべきだと思います
エンジニア

1
@Imranこれは私にはうまくいかないようです:私は得ますArgumentError: Unsupported argument type: #<MyModel::ActiveRecord_Relation:0x00007f8edbc075a8> (MyModel::ActiveRecord_Relation)
Suan

5
.orと同等で、関係を取得してand is is .mergeを生成します。(A || B)&&(C || D)はPost.where(a).or(Post.where(b))。merge(Post.where(c).or(Post.where(d )))
Siim Liiser

2
@MathieuJ。ActiveRecord :: Relation#mergeです。api.rubyonrails.org/classes/ActiveRecord/...
SIIM Liiser


6

(KM Rakibul Islamの回答に追加しただけです。)

スコープを使用すると、コードは見栄えがよくなります(見ている目によって異なります)。

scope a,      -> { where(a) }
scope b,      -> { where(b) }

scope a_or_b, -> { a.or(b) }

5

私はする必要がありました (A && B) || (C && D) || (E && F)

しかし、Rails 5.1.4の現在の状態では、これは複雑すぎてArelまたはチェーンで実行できません。しかし、私はまだRailsを使用してできるだけ多くのクエリを生成したいと思っていました。

だから私は小さなハックを作りました:

私のモデルでは、次の名前のプライベートメソッドを作成しましたsql_where

private
  def self.sql_where(*args)
    sql = self.unscoped.where(*args).to_sql
    match = sql.match(/WHERE\s(.*)$/)
    "(#{match[1]})"
  end

次に、スコープ内でORを保持する配列を作成しました

scope :whatever, -> {
  ors = []

  ors << sql_where(A, B)
  ors << sql_where(C, D)
  ors << sql_where(E, F)

  # Now just combine the stumps:
  where(ors.join(' OR '))
}

これにより、予想されるクエリ結果が生成されます SELECT * FROM `models` WHERE ((A AND B) OR (C AND D) OR (E AND F))

そして今、私はこれを他のスコープと簡単に組み合わせることができます。

私のsql_whereが通常のwhere句の引数をとるという美しさは、 sql_where(name: 'John', role: 'admin')を生成し(name = 'John' AND role = 'admin')ます。


.merge&&の同等物として使用して、括弧をキャプチャする適切なツリーを構築できると思います。...のような何か(scopeA.merge(scopeB)).or(scopeC.merge(scopeD)).or(scopeE.merge(scopeF))スコープのそれぞれを想定しては、のようなものに見えるModel.where(...)
nar8789

マージを使用する前にこれを確認してください-github.com/rails/rails/issues/33501
Aarthi

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.