如何增加属性,使其值(至少)比其他记录高1并且唯一

时间:2013-04-26 11:38:13

标签: ruby-on-rails activerecord

我有Payment模型,其属性为invoice_nr。此属性应在保存之前递增(加1)。所有payments都有唯一的invoice_nr

非常重要

我可以使用before_save回调,相对invoice_nrPayment.maximum("invoice_nr")增加1:

class Payment < ActiveRecord::Base
  before_save :increment_invoice_nr

  private
    def increment_invoice_nr
      self.invoice_nr = Payment.maximum("invoice_nr") + 1
    end
end

但我认为这并不能确保invoice_nr的独特性。如果两个payments同时保存,理论上可以得到相同的invoice_nr ......对吗?

如果invoice_nrs之间存在差距,也没关系,但如果您知道如何防止这种情况,您将获得奖励积分:)

修改

有些人建议使用大多数数据库具有的自动增量功能。这有效,但它会将我的应用程序绑定到我正在使用的特定数据库。因此,自动增量逻辑属于app imo。

5 个答案:

答案 0 :(得分:2)

您可以使用数据库序列。

迁移:

  def up
    execute 'CREATE SEQUENCE tr_num_seq START 10000000;'
  end

模型:

class model < ActiveRecord:Base
  after_initialize :set_omd_id
  def set_unique_number
        if self.tr_number.nil?
      self.tr_number = ActiveRecord::Base.connection.select_value("select nextval('tr_number_seq')")
    end
  end
end

每次创建模型对象时,如果尚未设置,将设置unqiue“发票编号ID”

答案 1 :(得分:1)

如果您的主键具有自动增量,则应该起作用

class Payment < ActiveRecord::Base
  after_save :increment_invoice_nr

  private
    def increment_invoice_nr
      some_high_integer = 10000000
      self.update_attribute('invoice_nr', self.id + some_high_integer)
    end
end

答案 2 :(得分:0)

我建议使用您选择的RDBMS中的自动增量功能。使用它你不必自己做,它是可靠的。

答案 3 :(得分:0)

您可以在模型中进行唯一验证。这样可以防止它保存重复值。 在您的付款方式中添加以下内容:

validates :invoice_nr, :uniqueness => true

如果您使用的是mysql或其他RDBMS

,也可以使用auto increment

答案 4 :(得分:0)

你可以试试这个。

def increment_invoice_nr
  invoice_nr_arr = Payment.all.map(&:invoice_nr)
  invoice = Payment.maximum("invoice_nr") 
  until invoice_nr_arr.include?(invoice) == false
    invoice += 1
  end
  self.invoice_nr = invoice
end

此方法将首先收集所有invoice_nr。然后它将检查增加的invoice_nr是否包含/存在于您的付款表中。如果它存在,那么它将继续将invoice_nr递增1,直到它获得唯一的invoice_nr。