Xây dựng dựa trên sự thật mà bạn đã khám phá ra rằng [1..5]
không phải là cách chính xác để chỉ định phạm vi ... Tôi đã khám phá ra lý do tại sao [1..5]
hành xử như nó làm. Để đến đó, trước tiên tôi thấy rằng một mảng trống trong điều kiện băm tạo ra 1=0
Điều kiện SQL:
User.where(id: []).to_sql
# => "SELECT \"users\".* FROM \"users\" WHERE 1=0"
Và nếu bạn kiểm tra ActiveRecord ::PredicateBuilder ::ArrayHandler mã , bạn sẽ thấy rằng các giá trị mảng luôn được phân chia thành các phạm vi và các giá trị khác.
ranges, values = values.partition { |v| v.is_a?(Range) }
Điều này giải thích tại sao bạn không thấy 1=0
khi sử dụng các giá trị không thuộc phạm vi. Đó là cách duy nhất để lấy 1=0
từ một mảng mà không bao gồm một dải ô là cung cấp một mảng trống, tạo ra 1=0
điều kiện, như được hiển thị ở trên. Và khi tất cả các mảng có trong nó là một phạm vi, bạn sẽ nhận được các điều kiện về phạm vi (ranges
) và riêng một điều kiện mảng trống (values
) Thực thi. Tôi đoán là không có lý do chính đáng cho điều này ... chỉ đơn giản là để điều này xảy ra hơn là tránh nó (vì tập kết quả là tương đương theo cả hai cách). Nếu mã phân vùng thông minh hơn một chút thì nó sẽ không phải giải quyết các giá trị values
bổ sung mảng và có thể bỏ qua 1=0
điều kiện.
Đối với nơi 1=0
đến từ nơi đầu tiên ... Tôi nghĩ rằng điều đó đến từ bộ điều hợp cơ sở dữ liệu, nhưng tôi không thể tìm thấy chính xác ở đâu. Tuy nhiên, tôi gọi đó là một nỗ lực không tìm được bản ghi. Nói cách khác, WHERE 1=0
sẽ không bao giờ trả lại bất kỳ người dùng nào, điều này có ý nghĩa so với SQL thay thế như WHERE id=null
sẽ tìm thấy bất kỳ người dùng nào có id là null (nhận ra rằng đây không phải là cú pháp SQL thực sự chính xác). Và đây là những gì tôi mong đợi khi cố gắng tìm tất cả Người dùng có id nằm trong tập hợp trống (tức là chúng tôi không yêu cầu id nil hoặc id rỗng hoặc bất cứ điều gì). Vì vậy, trong tâm trí tôi, hãy để lại một chút về vị trí chính xác 1=0
đến từ một hộp đen là OK. Ít nhất bây giờ chúng ta có thể giải thích lý do tại sao phạm vi bên trong của mảng khiến nó hiển thị!
CẬP NHẬT
Tôi cũng nhận thấy rằng, ngay cả khi sử dụng ARel trực tiếp, bạn vẫn có thể nhận được 1=0
:
User.arel_table[:id].in([]).to_sql
# => "1=0"