Answers:
让我们考虑基本示例:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
end
设置为default的动机published: true
可能是确保要显示未发布的(私人)帖子时必须让您明确。到目前为止,一切都很好。
2.1.1 :001 > Post.all
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."published" = 't'
好吧,这几乎是我们期望的。现在让我们尝试:
2.1.1 :004 > Post.new
=> #<Post id: nil, title: nil, published: true, created_at: nil, updated_at: nil>
这是默认范围的第一个大问题:
在这种模型的新创建实例中,default_scope
将反映出来。因此,尽管您可能希望确保不要偶然列出未发布的帖子,但现在默认情况下正在创建已发布的帖子。
考虑一个更详细的示例:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
belongs_to :user
end
class User < ActiveRecord::Base
has_many :posts
end
让我们获得第一个用户的帖子:
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]]
这看起来像预期的一样(请确保一直滚动到右侧,以查看有关user_id的部分)。
现在,我们要获取所有帖子的列表-包括未发布的-针对已登录用户的视图说。您将意识到必须“覆盖”或“撤消”的影响default_scope
。快速浏览Google之后,您可能会发现有关的信息unscoped
。看看接下来会发生什么:
2.1.1 :002 > User.first.posts.unscoped
Post Load (0.2ms) SELECT "posts".* FROM "posts"
=> Unscoped删除通常可能适用于您选择的所有范围,包括(但不限于)关联。
有多种方法可以覆盖的不同效果default_scope
。实现正确的选择很快就会变得很复杂,我认为一开始不使用default_scope
,将是一个更安全的选择。
unscoped
而不是default_scope
问题2
default_scope
想当您希望对某些内容进行排序时,是一个很好的选择:default_scope { order(:name) }
。
不使用的另一个原因default_scope
是,当您删除与该模型具有一对多关系的default_scope
模型实例时
考虑例如:
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
end
class Post < ActiveRecord::Base
default_scope { where(published: true) }
belongs_to :user
end
呼叫user.destroy
将删除所有的帖子published
,但不会删除所有的帖子unpublished
。因此,数据库将抛出外键冲突,因为它包含引用您要删除的用户的记录。