wrt*_*prt 120 ruby-on-rails default-scope
在 互联网上的 每个地方人们都提到使用rails default_scope是一个坏主意,而default_scopestackoverflow 的最高命中是关于如何覆盖它.这感觉很混乱,值得一个明确的问题(我认为).
所以:为什么使用rails default_scope这么坏主意?
wrt*_*prt 187
让我们考虑一下基本的例子:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
end
Run Code Online (Sandbox Code Playgroud)
制定默认值的动机published: true可能是确保在想要显示未发布的(私人)帖子时必须明确.到现在为止还挺好.
2.1.1 :001 > Post.all
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."published" = 't'
Run Code Online (Sandbox Code Playgroud)
嗯,这几乎是我们所期望的.现在让我们尝试:
2.1.1 :004 > Post.new
=> #<Post id: nil, title: nil, published: true, created_at: nil, updated_at: nil>
Run Code Online (Sandbox Code Playgroud)
我们有默认范围的第一个大问题:
在这种模型的新创建的实例中,default_scope将反映出来.因此,虽然您可能希望确保不会偶然列出未发布的帖子,但您现在默认创建已发布的帖子.
考虑一个更详细的例子:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
belongs_to :user
end
class User < ActiveRecord::Base
has_many :posts
end
Run Code Online (Sandbox Code Playgroud)
让我们得到第一个用户帖子:
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]]
Run Code Online (Sandbox Code Playgroud)
这看起来像预期的(确保一直向右滚动以查看有关user_id的部分).
现在我们想要获取所有帖子的列表 - 未发布包括 - 比如登录用户的视图.你会发现你必须'覆盖'或'撤消'效果default_scope.快速谷歌后,你可能会发现unscoped.看下一步会发生什么:
2.1.1 :002 > User.first.posts.unscoped
Post Load (0.2ms) SELECT "posts".* FROM "posts"
Run Code Online (Sandbox Code Playgroud)
=> Unscoped删除通常可能适用于您的选择的所有范围,包括(但不限于)关联.
有多种方法可以覆盖不同的效果default_scope.做到这一点很快就会很复杂,我认为不首先使用它default_scope会是一个更安全的选择.
小智 6
通常建议不要使用default_scope,因为有时会错误地使用它来限制结果集。default_scope的一个很好的用途是对结果集进行排序。
我会避免where在default_scope中使用它,而是为此创建一个范围。
小智 6
不使用的另一个原因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
Run Code Online (Sandbox Code Playgroud)
调用user.destroy将删除所有已发布的帖子published,但不会删除所有已发布的帖子unpublished。因此,数据库将引发外键冲突,因为它包含引用您要删除的用户的记录。
| 归档时间: |
|
| 查看次数: |
27334 次 |
| 最近记录: |