Relation là một mô tả query chưa chạy.
Rails chỉ gửi SQL xuống DB khi bạn thực sự cần tới dữ liệu — gọi là loading.
ruby
scope = User.where(active: true).order(:created_at) # chưa chạy SQL
scope = scope.limit(10) # vẫn chưa có SQL, mới chỉ chain
scope.to_a # SQL chạy ở đâyKích hoạt query: to_a, each, first, last, find, count, sum, pluck, any?, hoặc khi render trong view. Không kích hoạt: where, order, limit, joins, includes, select — chúng chỉ trả về Relation mới.
Hai điểm hay bị hỏi tiếp:
- Relation cache kết quả sau lần load đầu; gọi each lần hai không chạy lại SQL. Muốn ép chạy lại thì dùng reload.
- Mỗi lần chain là một Relation mới (bất biến), nên scope.where(...) không sửa scope gốc.
Lazy chính là lý do có thể tách điều kiện ra nhiều tầng (scope, controller, service) mà cuối cùng vẫn chỉ có một câu SQL.