Vấn đề 1
Hãy xem xét ví dụ cơ bản:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
end
Động lực để làm mặc định published: true
, có thể là để đảm bảo bạn phải bùng nổ khi muốn hiển thị các bài đăng (riêng tư) chưa được công bố. Càng xa càng tốt.
2.1.1 :001 > Post.all
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."published" = 't'
Vâng, đây là khá nhiều những gì chúng ta mong đợi. Bây giờ hãy thử:
2.1.1 :004 > Post.new
=> #<Post id: nil, title: nil, published: true, created_at: nil, updated_at: nil>
Và ở đó chúng ta có vấn đề lớn đầu tiên với phạm vi mặc định:
=> default_scope sẽ ảnh hưởng đến việc khởi tạo mô hình của bạn
Trong một ví dụ mới được tạo ra của một mô hình như vậy, default_scope
sẽ được phản ánh. Vì vậy, trong khi bạn có thể muốn chắc chắn không liệt kê các bài đăng chưa được công bố một cách tình cờ, thì bây giờ bạn đang tạo các bài đăng được xuất bản theo mặc định.
Vấn đề 2
Hãy xem xét một ví dụ phức tạp hơn:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
belongs_to :user
end
class User < ActiveRecord::Base
has_many :posts
end
Cho phép nhận bài đăng của người dùng đầu tiên:
2.1.1 :001 > User.first.posts
Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."published" = 't' AND "posts"."user_id" = ? [["user_id", 1]]
Điều này trông giống như mong đợi (đảm bảo cuộn toàn bộ sang bên phải để xem phần về user_id).
Bây giờ chúng tôi muốn lấy danh sách tất cả các bài đăng - chưa được công bố - nói về chế độ xem của người dùng đã đăng nhập. Bạn sẽ nhận ra rằng bạn phải 'ghi đè' hoặc 'hoàn tác' hiệu ứng của default_scope
. Sau khi google nhanh, bạn có thể sẽ tìm hiểu về unscoped
. Xem những gì xảy ra tiếp theo:
2.1.1 :002 > User.first.posts.unscoped
Post Load (0.2ms) SELECT "posts".* FROM "posts"
=> Unscoped loại bỏ TẤT CẢ phạm vi thường có thể áp dụng cho lựa chọn của bạn, bao gồm (nhưng không giới hạn) các liên kết.
Có nhiều cách để ghi đè lên các hiệu ứng khác nhau của default_scope
. Nhận quyền đó trở nên phức tạp rất nhanh và tôi sẽ tranh luận rằng không sử dụng ngay default_scope
từ đầu, sẽ là lựa chọn an toàn hơn.