RAILS-强制ActiveRecord模型中.save和.update的条件

问题描述

我通过名为account_id的列对表postgres表进行了分区

进行查询时,我有一个gem使用default_scope并自动添加where,这很好,但是我也需要在model.save和model.update中使用where条件。

我了解到认范围不会触发模型更新,我可以做些什么添加到模型的保存和更新语句中吗?

示例:

Model.update(name: "X)生成:更新模型集名称=“ X”,其中id ='1'

但是我需要这个:

Model.update(name: "X)生成:更新模型集名称=“ X”,其中id ='1'并且account_id = model.account_id

我尝试过这样的操作:Model.where(id: model.id).update_all(name: "X),它可以工作,但是我需要在应用程序中进行很多更改。

我正在使用rails6

谢谢。

解决方法

首先,Model.updateModel.update_all非常不同,例如后者会忽略您可能拥有的所有验证和回调。

第二,Model.update期望将ID或ID数组作为第一个参数传递,如果不传递它-它假设:all个ID,请检查实现:

def update(id = :all,attributes)
  if id.is_a?(Array)
    # [cut for clarity]
  elsif id == :all
    all.each { |record| record.update(attributes) } #<--- HERE
  else
    # [more cut off for clarity

因此Model.update不应在任何其他条件下使用,因为它希望将实际的主键传递给它。

我这样尝试过:Model.where(id:model.id).update_all(name:“ X”) 是的,但是在底层,该框架执行的操作与update完全不同,您可能不希望这样做。而是这样做:


Model.update(Model.where(YOUR_CONDITION_HERE).ids,name: 'X')

(您的问题还不清楚应该是什么情况)。

but I would need to change many many things in the application.

好吧,一些重构就是这样。

!不建议使用以下内容,仅出于教育目的!

有一种方法可以使Model.update(name: "X)正常工作,但这会改变方法的行为(对于Model,它将是不同的方法,对于所有其他模型,其行为将不一致) :


class Model < ApplicationRecord
  def self.update(attributes)
    where(YOUR_CONDITION_HERE).update_all(attributes)
  end
end

请不要这样做,会使您的代码库更糟。