Rails:如何增加模型的选定实例的整数字段?

Buyer模型有两个字段:

  • 名字(字符串)
  • 位置(整数)

我想增加position >= N的所有买家的position >= N

最简单的方法是什么?

只使用一个查询就可以实现这一点吗?

你可以使用:

 Buyer.update_all("position = position + 1", ["position >= ?", n]) 

如果n = 25,这将生成查询:

 UPDATE "buyers" SET position = position + 1 WHERE (position >= 25) 

编辑:

由于您具有UNIQUE数据库约束,因此您有两种选择。 对于这两个选项,我建议在事务中运行它们。 首先,您可以按相反顺序单独更新每个字段,但这将导致您进行N + 1个查询。 对于小型数据集,这不是问题,但对于较大的数据集,这可能会影响性能。

 Buyer.transaction do Buyer.select("id, position").where(["position >= ?", n]).order("position DESC").each do |buyer| buyer.position += 1 buyer.save end end 

避免N + 1个查询的另一个选项是将位置增量更改为100(或10)。 这将允许您更新两个查询中的位置,而不是N + 1。 因此,不是拥有位置1,2,3等,而是拥有100,200,300等。然后进行更新,您将所有值增加101,然后按照更新进行更新以减去1。

 Buyer.transaction do Buyer.where(["position >= ?", n]).scoping do Buyer.update_all("position = position + 101") Buyer.update_all("position = position - 1") end end 

如果这是临时的,您可以删除约束/索引,运行更新,然后使用常规旧SQL重新添加它。

 class Buyer < ActiveRecord::Base scope :positioned_at_or_above, lambda {|pos| where("position >= ?", pos) } def self.increment(amount, position_threshold) Buyer.positioned_at_or_above(position_threshold).each{|buyer| buyer.update_attributes(:position => buyer.position + amount)} end end 

 increment ∴ rails c Loading development environment (Rails 3.0.3) >> Buyer.count => 0 >> (1..10).each {|idx| Buyer.create(:name => "Buyer ##{idx}", :position => idx)} => 1..10 >> pp Buyer.all [#, #, #, #, #, #, #, #, #, #] => nil >> pp Buyer.positioned_at_or_above(4) [#, #, #, #, #, #, #] => nil >> pp Buyer.positioned_at_or_above(4).all [#, #, #, #, #, #, #] => nil >> Buyer.increment(1000, 4) => [#, #, #, #, #, #, #] >> pp Buyer.all [#, #, #, #, #, #, #, #, #, #] => nil >>