gpt4 book ai didi

ruby-on-rails - 验证一批更新

转载 作者:行者123 更新时间:2023-12-04 06:22:03 24 4
gpt4 key购买 nike

在 Rails 应用程序中,是否可以一次进行一批更改,仅验证更改的最终结果而不是每个单独的步骤?

这是一个有点含糊不清的问题,所以让我们把它说得具体一点。假设我有一个杂货店应用程序:

class Store < ActiveRecord::Base
has_many :fruits
end

class Fruit < ActiveRecord::Base
belongs_to :store
attr_accessible :kind, :number, :price
validates_uniqueness_of :kind, :scope => :store_id
end

我已使用以下数据为数据库播种:
fruits:
store_id | kind | number | price
----------------------------------------
1 | apple | 10 | 0.15
1 | banana | 80 | 0.02
1 | cherry | 25 | 0.50

但我意识到我搞砸了,交换了香蕉和樱桃的数量和价格。我不能这样做:
store = Store.find(1)
old_bananas = store.fruits.where("kind = banana").first
old_cherries = store.fruits.where("kind = cherry").first
old_bananas.kind = "cherry"
old_cherries.kind = "banana"
old_bananas.save! # => Validation Error
old_cherries.save!

因为在保存第一行时违反了唯一性约束,即使在保存第二行之后也可以。是否可以将两个保存一起批处理,并让验证只看到一次进行所有更改的结果?

(我可以想到解决方法 - 例如,如果我进行了验证 :allow_nil ,然后在更改任何一行之前将每一行清零 - 但我想知道是否存在“适当的”解决方案)

最佳答案

如果您的约束只是验证,但您没有在数据库中强制执行的唯一索引,请使用 update_attribute 方法 - 它跳过验证。

store.fruits.where("kind = banana").first.update_attribute(:kind, "cherry")
store.fruits.where("kind = cherry").first.update_attribute(:kind, "banana")

或者简单地使用 save(validate: false)而不是 save! .

编辑:因为你有一个唯一的索引,死简单的解决方案是使用一个临时值:
store.fruits.where("kind = banana").first.update_attribute(:kind, "foo")
store.fruits.where("kind = cherry").first.update_attribute(:kind, "banana")
store.fruits.where("kind = foo" ).first.update_attribute(:kind, "cherry")

我不知道在 SQL 中就地交换行之间的值的方法,这确实是这里的问题,因为可以轻松绕过模型级验证。

关于ruby-on-rails - 验证一批更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13475410/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com