【问题标题】:Update a relation in a scope?更新范围内的关系?
【发布时间】:2014-09-04 20:23:47
【问题描述】:

我怎样才能拥有像 ActiveRecord scope 这样的东西来修改它所作用的关系?

具体来说,我希望能够做到这一点:

Model.some_scope.fake_destroy_all

fake_destroy_all 是我正在尝试创建的功能。它几乎等同于.update_all(deleted: true)

一个较弱的选择是:

def fake_destroy_all(relation = Model)
    relation.update_all(deleted: true)
end

#...

Model.fake_destroy_all(Model.some_scope)

但这并不理想。我想做的是:

scope :fake_destroy_all, update_all(deleted: true)

但这不起作用。

有没有可能像我描述的那样做?

【问题讨论】:

标签: ruby-on-rails ruby activerecord


【解决方案1】:

试试这个:

def self.fake_destroy_all
  self.update_all(deleted: true)
end

事实证明,关系保留了所有的类方法。范围也是类方法,它是允许范围“链接”的确切机制。

因此,与此模型的关系也将具有此方法,self 是关系的一个实例。

范围语法可能可以像这样固定(现在无法测试,但请注意 lambda 而不是简单的方法调用):

scope :fake_destroy_all, -> { update_all(deleted: true) }

我想,无需在 lambda 内更新,它在类定义上调用 scope 时会有效地调用此方法。它确实适用于简单的 where 类型范围,因为 where 没有副作用,它只返回一个适用的过滤器。它被评估一次并保存在一个方法中以供将来使用。

使用 lambda,但是,执行会一直保持到实际应用范围,而不是直到定义。这是必要的,因为update_all 确实有副作用

如果您指定一个条件不断变化的范围,同样的技巧很有用,最简单的情况是对Time.now 的依赖,它随着时间的推移而变化,每次都需要重新评估。

但是,我建议您使用类方法:作用域更像是过滤器,而这更像是“过滤器强制执行”。虽然这也可能有效,但范围在语义上适用于不同的用例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多