2011-06-29 21 views
5

Mô hình có hai thuộc tính quan tâm, cho tênthị trấn. Tôi muốn tìm Richard (London) và Brian (Madrid).Rails/Arel - ưu tiên khi kết hợp các thuộc tính AREL

Trong dài tay,

p=Person.scoped 
pred1=p.table[:forename].eq('Richard').and(p.table[:town].eq('London')) 
pred2=p.table[:forename].eq('Brian').and(p.table[:town].eq('Madrid')) 
pred3=pred1.or(pred2) 

tôi sẽ mong đợi điều này để bọc các vị từ trong ngoặc để duy trì tính toàn vẹn của truy vấn. Nhưng nhìn vào pred3.to_sql cho một phản ứng bất ngờ:

"(`person`.`forename` = 'Richard' AND `person`.`town` = 'London' OR `person`.`forename` = 'Brian' AND `person`.`town` = 'Madrid')" 

Làm cách nào để Arel có thể tạo truy vấn đúng?

+1

Bạn đã bao giờ tìm được giải pháp cho điều này chưa? Tôi gặp vấn đề tương tự và câu trả lời được đề xuất không hoạt động. – CrashRoX

+0

@CrashRoX, tôi đã đăng câu trả lời bên dưới. – John

Trả lời

2

Điều này thực sự là là truy vấn chính xác, vì AND có ưu tiên toán tử cao hơn OR trong hầu hết các phương ngữ SQL. Nếu bạn lật nó và AND OR OR predicates, nó sẽ bọc các OR predicates trong paren.

t = Arel::Table.new('blah') 

a = (t[:a].eq(nil).and(t[:b].eq(nil))) 
b = (t[:a].not_eq(nil).and(t[:b].not_eq(nil))) 
a.or(b).to_sql 

    => "(`blah`.`a` IS NULL AND `blah`.`b` IS NULL OR `blah`.`a` IS NOT NULL AND `blah`.`b` IS NOT NULL)" 

a = (t[:a].eq(nil).or(t[:b].eq(nil))) 
b = (t[:a].not_eq(nil).or(t[:b].not_eq(nil))) 
a.and(b).to_sql 

    => "(`blah`.`a` IS NULL OR `blah`.`b` IS NULL) AND (`blah`.`a` IS NOT NULL OR `blah`.`b` IS NOT NULL)" 
0

Hãy thử sử dụng arel_table trực tiếp

person_table = Person.arel_table 
pred1 = person_table[:forename].eq("Richard").and(person_table[:town].eq("London")) 
pred2 = person_table[:forename].eq("Rick").and(person_table[:town].eq("US")) 
pred1.or(pred2).to_sql 

này mang lại (("người". "Tên đầu tiên" = 'Richard' AND "nhân dân". "Thị trấn" = 'London') OR ("người". "forename" = 'Rick' AND "people". "town" = 'US'))

1

Đối với đường ray 3.2.13, sử dụng Arel::Nodes::Grouping. Xem thêm FactoryMethods#grouping-instance_method RubyDoc.

pt = Person.arel_table 
pred1 = person_table[:forename].eq("Richard").and(person_table[:town].eq("London")) 
pred2 = person_table[:forename].eq("Rick").and(person_table[:town].eq("US")) 
pt.grouping(pred1).or(pt.grouping(pred2)).to_sql 

=> (("people"."forename" = 'Richard' AND "people"."town" = 'London') OR ("people"."forename" = 'Rick' AND "people"."town" = 'US')) 
Các vấn đề liên quan