为什么使用rails default_scope经常推荐反对?

在互联网上 的任何 地方 ,人们都提到,使用rails default_scope是一个坏主意,而stackoverflow上的default_scope的顶部命中是关于如何覆盖它。 这感觉搞砸了,值得一个明确的问题(我认为)。

所以:为什么使用rails default_scope这样一个坏主意?

问题1

让我们考虑一下基本的例子:

 class Post < ActiveRecord::Base default_scope { where(published: true) } end 

使默认published: true的动机published: true ,可能是为了确保在显示未发布的(私人)post时必须进行解释。 到现在为止还挺好。

 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会影响你的模型初始化

在这个模型的新创build的实例中, default_scope将被反映。 因此,虽然您可能希望确保不偶然列出未发布的post,但您现在默认创build发布的post。

问题2

考虑一个更详细的例子:

 class Post < ActiveRecord::Base default_scope { where(published: true) } belongs_to :user end class User < ActiveRecord::Base has_many :posts end 

让我们获取第一个用户的post:

 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的部分)。

现在,我们要获取所有文章的列表 – 未发布包括 – 说已login用户的视图。 你会意识到你必须“覆盖”或“撤销” default_scope的效果。 经过一个快速的谷歌,你可能会发现关于unscoped 。 看看下面会发生什么:

 2.1.1 :002 > User.first.posts.unscoped Post Load (0.2ms) SELECT "posts".* FROM "posts" 

=> Unscoped删除所有可能通常适用于您select的范围,包括(但不限于)关联。

有多种方法可以覆盖default_scope的不同效果。 这样做很快就会变得复杂 ,我认为不首先使用default_scope会是一个更安全的select。

通常推荐使用default_scope,因为有时会错误地使用default_scope来限制结果集。 default_scope的一个很好的用法是命令结果集。

我会远离使用default_scope的地方,而是为此创build一个范围。

    Interesting Posts