为什么使用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一个范围。