Mô hình Rails tìm nơi không bằng


127

Làm thế nào tôi có thể tìm thấy các bản ghi trong cơ sở dữ liệu của tôi trong một điều kiện không bằng nhau? Bây giờ tôi có cái này, nhưng có một cách nói lạ mắt nào không?

GroupUser.where('user_id != ?',me)

Những gì bạn có là khá nhiều cách tốt Rails 3 tôi nghĩ.
Spyros

Câu trả lời:


229

Trong Rails 4.x (Xem http://edgeguides.rubyonrails.org/active_record_querying.html#not-conditions )

GroupUser.where.not(user_id: me)

Trong Rails 3.x

GroupUser.where(GroupUser.arel_table[:user_id].not_eq(me))

Để rút ngắn độ dài, bạn có thể lưu trữ GroupUser.arel_tabletrong một biến hoặc nếu sử dụng bên trong mô hình GroupUser, ví dụ: trong a scope, bạn có thể sử dụng arel_table[:user_id]thay vìGroupUser.arel_table[:user_id]

Cú pháp 4.0 tín dụng cho câu trả lời của @ jbearden


Còn trong các hiệp hội thì sao? - has_many: group_users, -> {where.not (trạng thái: "Đã từ chối")}, thông qua :: Groups, Foreign_key: "user_id"
ajbraus

4
Một ghi chú bên lề, nó cũng hoạt động tốt trong chuỗi:GroupUser.where(other_condition: true).where.not(user_id: user_id)
Enrico Carlesso


26

Cách duy nhất bạn có thể có được nó fancier là với MetaWhere .

MetaWhere có một người anh em họ mới hơn được gọi là Squeel cho phép mã như thế này:

GroupUser.where{user_id != me}

Không cần phải nói, rằng nếu đây là công cụ tái cấu trúc duy nhất bạn sẽ thực hiện, thì không đáng để sử dụng đá quý và tôi sẽ chỉ gắn bó với những gì bạn có. Squeel rất hữu ích trong các tình huống khi bạn có nhiều truy vấn phức tạp tương tác với mã Ruby.


4
MetaWhere là tuyệt vời, nhưng nhiệm vụ này có thể được thực hiện mà không cần thêm đá quý.
tybro0103

1
@ tybro0103 tất nhiên nhiệm vụ có thể được thực hiện (và imho theo cách OP đang làm nó là hoàn toàn tốt), câu hỏi là về việc thực hiện nó fancier. Vì vậy, nếu bạn nghĩ rằng nó có thể được thực hiện fancier mà không cần đá quý, tôi sẽ rất quan tâm đến cách làm điều đó.
Jakub Hampl

Câu trả lời của Vikrant không cung cấp giải pháp không liên quan đến sql hoặc bao gồm một loại đá quý khác. Nhưng, tôi đứng chính xác, câu trả lời của bạn chắc chắn là thân thiện với người lập trình / ưa thích nhất.
tybro0103

1
thêm một viên đá quý để hoàn thành một nhiệm vụ đơn giản như vậy. Đánh bóng mờ với bazooka
baash05

Đây là quá mức cần thiết.
Courtimas

23

Đường ray 4:

Nếu bạn muốn sử dụng cả không bằng nhau và bằng nhau, bạn có thể sử dụng:

user_id = 4
group_id = 27
GroupUser.where(group_id: group_id).where.not(user_id: user_id)

Nếu bạn muốn sử dụng nhiều loại toán tử (ví dụ. >, <), Tại một số điểm bạn có thể muốn chuyển các ký hiệu sau:

GroupUser.where("group_id > ? AND user_id != ?", group_id, user_id)

Thế còn GroupUser.where(group_id: group_id).where.not(user_id: user_id)?
Enrico Carlesso

@EnricoCarlesso Cảm ơn bạn đã đăng bài. Tôi cập nhật câu trả lời của tôi để bao gồm đề nghị của bạn. Cảm ơn.
Rick Smith

9

Bạn phải luôn luôn bao gồm tên bảng trong truy vấn SQL khi xử lý các liên kết.

Thật vậy, nếu một bảng khác có user_idcột và bạn tham gia cả hai bảng, bạn sẽ có một tên cột mơ hồ trong truy vấn SQL (nghĩa là rắc rối).

Vì vậy, trong ví dụ của bạn:

GroupUser.where("groups_users.user_id != ?", me)

Hoặc dài hơn một chút:

GroupUser.where("#{table_name}.user_id IS NOT ?", me)

Lưu ý rằng nếu bạn đang sử dụng hàm băm, bạn không cần phải lo lắng về điều đó vì Rails chăm sóc nó cho bạn:

GroupUser.where(user: me)

Trong Rails 4, như đã nói bởi @ dr4k3, phương thức truy vấn notđã được thêm vào:

GroupUser.where.not(user: me)

6

Trong Rails 3, tôi không biết gì về người hâm mộ. Tuy nhiên, tôi không chắc nếu bạn biết, điều kiện không bằng của bạn không khớp với các giá trị NULL (user_id). Nếu bạn muốn điều đó, bạn sẽ phải làm một cái gì đó như thế này:

GroupUser.where("user_id != ? OR user_id IS NULL", me)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.