Bạn có chắc chắn muốn xóa bài viết này không ?
Bạn có chắc chắn muốn xóa bình luận này không ?
Cẩn thận khi sử dụng select cùng với find_in_batches trong rails
Vấn đề
Hôm nay mình gặp trường hợp sử dụng custom select các trường không phải primary key cùng với find_in_batches
, nếu số lượng record nhỏ hơn batch_size
, sẽ không có lỗi nào được raise lên. Ngược lại, có thể sẽ có:
RuntimeError: Primary key not included in the custom select clause
Một ví dụ đơn giản:
Person.select('person.firstname').find_in_batches do |group|
group.each { |person| puts person.firstname }
end
Đoạn code trên sẽ chạy êm ru nếu trong db của bạn có ít hơn 1000 users. Đến khi bảng users
của bạn có record thứ 1001, lỗi sẽ được raise lên ngay khi gọi.
Lỗi này thường không bắt được bằng automation test (trừ khi có performance test) nên rất dễ xảy ra ở môi trường production.
Tham khảo thêm ở: http://apidock.com/rails/ActiveRecord/Batches/find_in_batches#1535-Be-careful-with-select
Cách khắc phục
Đọc mã nguồn của ActiveRecord 5.0 ta có thể thấy:
if load
# ...
ids = records.map(&:id)
# ...
else
# ...
ids = batch_relation.pluck(primary_key)
# ...
end
# ...
primary_key_offset = ids.last
raise ArgumentError.new("Primary key not included in the custom select clause") unless primary_key_offset
Như vậy, để tránh (và sửa) lỗi này, bạn chỉ cần thêm vào primary key trong câu lệnh select
. Nếu câu query này là một câu lệnh phức tạp mà không thể chỉ định primary key (hoặc Rails version nhỏ hơn 5) thì bạn có thể đổi tên một trường thành id
để thoả mãn yêu cầu của Rails.






