【问题标题】:Is there a way to add default_scope with update_columns and delete in rails有没有办法用 update_columns 添加 default_scope 并在 rails 中删除
【发布时间】:2020-08-16 01:30:45
【问题描述】:

在基于Rails 5.2.4.1 的应用程序中,我们希望将default_scope 添加到应用程序中运行的所有查询中。 select 查询尊重default_scope,但update_columnsdeleteupdate 不尊重default_scope

我在 rails 3.2 中找到了一个与此非常相关的 old issue,但它已在 this commit 中修复。现在在 Rails 5.2 我找不到任何可能的方法来做到这一点。

提前致谢。

【问题讨论】:

  • 范围用于集合。所有提到的update_columnsdeleteupdate 方法都是针对单个记录而不是集合调用的。在单个记录(即实例)上应用范围时的预期行为是什么?
  • Model.find(id) 应用默认范围。
  • 是的,这需要集合。假设您有instance = Model.unscoped.find(id),您希望在运行instance.update_columns(attribute: 'value') 时如何应用默认范围?当instance 符合默认范围时,预期的结果是什么?当instance 不符合默认范围时,您期望什么?
  • 我明白你的意思。但实际上我们有default_scope 作为当前的company_Id,并且所有查询都应该有company_id,所以我们可以将特定的company_id 查询转发到它们各自的数据库。这就像基于查询的数据库分片。所以我们需要更新查询有 company_id
  • default_scopes 通常是个坏主意。除非您能找到一种方法,只需一次调用即可使其项目范围广泛,那么为什么不使用自定义范围呢?你稍后会在使用 default_scopes 的大型项目中遇到问题

标签: ruby activerecord ruby-on-rails-5


【解决方案1】:

Rails 6.1 all_queries: true 默认范围选项

From BigBinary blog:

在 Rails 6.1 之前,如果在模型中定义了 default_scope,它将仅适用于 selectinsert 查询。 Rails 6.1 添加了一个选项all_queries: true,可以将其传递给default_scope,以使范围适用于所有查询。

default_scope -> { where(...) }, all_queries: true

考虑下面的 Article 类。

class Article
  default_scope -> { where(organization_id: Current.organization_id) }
end

@article.update title: "Hello World"
@article.delete

updatedelete 方法将生成 SQL 查询,如下所示。正如我们所见,这些查询中缺少default_scope

UPDATE "articles" SET "title" = $1 WHERE "articles"."id" = $2 [["title", "Hello World"], ["id", 146]]

DELETE FROM "articles" WHERE "articles"."id" = $1  [["id", 146]]

在 Rails 6.1 中,我们可以通过将 all_queries: true 传递给 default_scope 来解决这个问题。

class Article
  default_scope -> { where(organization_id: Current.organization_id) }, all_queries: true
end

然后生成的SQL变成这样:

UPDATE "articles" SET "title" = $1 WHERE "articles"."id" = $2 AND "articles"."organization_id" = $3  [["title", "Hello World"], ["id", 146], ["organization_id", 314]]

DELETE FROM "articles" WHERE "articles"."id" = $1 AND "articles"."organization_id" = $2  [["id", 146], ["organization_id", 314]]

来源:

【讨论】:

  • 这个答案不正确。引用的博客文章有误,并直接说该功能是 Rails 6.1 的一部分 - 它没有进入任何 6.x 版本github.com/rails/rails/blob/v6.1.4/activerecord/lib/…。从外观上看,它将成为 Rails 7 的一部分,但在此之前显然可以出于任何原因撤消。
猜你喜欢
  • 2015-06-19
  • 1970-01-01
  • 2011-03-12
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
  • 2015-04-02
  • 1970-01-01
  • 2015-03-04
相关资源
最近更新 更多