Rails 5: ActiveRecord VEYA sorgusu


Yanıtlar:


228

Sorgudaki ormadde ile birlikte whereyan tümceyi zincirleme yeteneği ActiveRecord, Rails 5'te mevcut olacaktır . Bkz ilgili tartışma ve çekme isteğini .

Böylece, Rails 5'te aşağıdakileri yapabileceksiniz :

1 veya 2 postile bir almak için id:

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

Diğer bazı örnekler:

(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) 'yi nasıl alabilirim. Post.where (a) .or (Post.where (b)) 'yi denedim. Burada (c) .or (Post.where (d)) ama şu şekilde üretir: (A || B) && C || D
Imran Ahmad

3
@Imran Bunun Post.where(a).or(Post.where(b)).where(Post.where(c).or(Post.where(d)))yaratması gerektiğine inanıyorum (a || b) && (c || d)
engineersmnky

1
@Imran Bu benim için işe yaramıyor gibi görünüyor: AnladımArgumentError: Unsupported argument type: #<MyModel::ActiveRecord_Relation:0x00007f8edbc075a8> (MyModel::ActiveRecord_Relation)
Suan

5
Bir ilişki alan ve üreten ve .merge olan .or ifadesinin eşdeğeri. (A || B) && (C || D) Post.where (a) .or (Post.where (b)) tarafından üretilebilir. Merge (Post.where (c) .or (Post.where (d) )))
Siim Liiser

2
@MathieuJ. ActiveRecord :: İlişki # birleştirme. api.rubyonrails.org/classes/ActiveRecord/…
Siim Liiser

13

Bu ORsorguyu kullanmak için rayların 5 beklemesine gerek yok . İle de kullanabiliriz rails 4.2.3. Burada bir arka port var .

Eric-Guo'ya mücevher için teşekkürler - veya , Şimdi bu ORişlevi >= rails 4.2.3bu mücevheri kullanarak da ekleyebiliriz .


6

(KM Rakibul Islam'ın cevabına sadece bir ek.)

Kapsamları kullanarak kod daha güzel hale gelebilir (bakan gözlere bağlı olarak):

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

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

5

Yapmam gerek (A && B) || (C && D) || (E && F)

Ancak Rails'in 5.1.4şu anki durumunda bu, Arel veya zincir ile başarılamayacak kadar karmaşık. Ancak yine de mümkün olduğunca fazla sorgu oluşturmak için Rails'i kullanmak istedim.

Bu yüzden küçük bir hack yaptım:

Modelimde özel bir yöntem oluşturdum sql_where:

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

Ardından, kapsamımda ameliyathaneleri tutmak için

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 '))
}

Hangi beklenen sorgu sonucu üretecektir: SELECT * FROM `models` WHERE ((A AND B) OR (C AND D) OR (E AND F)).

Ve şimdi bunu herhangi bir yanlış OR'ler olmadan diğer kapsamlarla vb. Kolayca birleştirebilirim.

Sql_where'in normal where-clause argümanlarını alması güzelliği: sql_where(name: 'John', role: 'admin')üretecek (name = 'John' AND role = 'admin').


Sanırım .merge&& eşdeğeri olarak kullanabilir ve parenslerinizi yakalamak için uygun bir ağaç inşa edebilirsiniz. (scopeA.merge(scopeB)).or(scopeC.merge(scopeD)).or(scopeE.merge(scopeF))Her bir kapsamın şuna benzediğini varsayarsak ... gibi bir şeyModel.where(...)
nar8789

Birleştirmeyi kullanmadan önce bunu kontrol edin - github.com/rails/rails/issues/33501
Aarthi

1

Rails 5, orile madde kullanma yeteneğine sahiptir where. Örneğin.

User.where(name: "abc").or(User.where(name: "abcd"))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.