【问题标题】:Ruby on Rails: Custom Alphanumeric id based on another field and Auto increment itRuby on Rails:基于另一个字段的自定义字母数字 ID 并自动递增它
【发布时间】:2014-04-07 12:10:25
【问题描述】:

在开始之前,我必须说我是 Ruby on rails 的新手。

我有一个名为 Vendor 的模型。我想要一个字段 vendorid,它应该是一个字母数字字段。我想自动增加它。

我也有一个城市,它是同一模型中的下拉选择字段。我希望我的 vendorid 在其值中使用该字段。

例如:如果我的第一个 Vendors 条目的城市为 HYD,我希望我的 vendorid 为 HYD001,如果下一个条目的城市为 DEL,则 vendorid 应为 DEL001,否则如果它的城市再次为 HYD,则应该是 HYD002。

在网上搜索了很多后,我找到了 gem protokoll。但我认为即使这样也无助于我的情况。

class Vendor < ActiveRecord::Base    
    protokoll :vendorid, :pattern => city + "###"
end

我也试过了:

:pattern => "#{城市}###" :pattern => self.city + "###"

它给我一个错误“#Class:0xb61c4150 的未定义方法 `city'”

感谢您的帮助。

【问题讨论】:

  • Protokoll 看起来会做你想做的事(虽然我自己没有使用过)。 Protokoll 有什么问题?
  • 我已经编辑了这篇文章,展示了我对 protokoll 所做的事情以及我的结果。
  • 在您的代码中,当 rails 加载时,“city”正在类级别使用。那时它不知道city 是什么。看起来您正在尝试猜测 Protokoll 的语法,以告诉它使用城市值而不是固定字符串。这可能是不可能的,但如果是这样,那绝对不是正确的语法。
  • 同样的问题:“self”是类。没有Vendor.city 方法。

标签: mysql ruby-on-rails auto-increment


【解决方案1】:

暂时忘记 Protokoll,我认为这应该可行。

class Vendor
  before_create :set_unique_vendorid

  def set_unique_vendorid
    if last_vendor = Vendor.find(:last, :order => "id", :conditions => ["vendorid like ?", "#{self.city}%"])
      last_vendorid_number = last_vendor.vendorid.scan(/\d+$/).first.to_i
      new_vendorid_number = last_vendorid_number + 1
    else
      new_vendorid_number = 1
    end
    self.vendorid = "#{self.city}#{sprintf("%03d", new_vendorid_number)}"
  end

sprintf 位会将 new_vendorid_number 转换为三位数的字符串(例如“002”),这看起来像是您的要求。

注意:如果您的服务器运行多个 Rails 实例,并且其中两个尝试同时创建一个新的 Vendor 对象,则此处可能存在竞争条件。但是,如果你到了如此成功的地步,你需要担心这一点,那么你可以用事务或其他东西来重构它:O

【讨论】:

  • 嗨 Max,非常感谢您提供的解决方案,我一直在自己尝试并做了与您类似的事情。我不知道这是否是正确的解决方案,但它给了我正确的答案。而不是 last_ventorid_number 我得到了像 "count = Vendor.count(:conditions => ["city == ?", city])" 这样的计数并添加了 101。这有什么后果吗?正如我之前告诉过你的,我对这一切都很陌生。
  • 基于count 并不能保证唯一性。例如:您创建了第一个 HYD 供应商,它得到 vendorid = "HYD101"。你在 HYD 中再做一个,它得到 vendorid = "HYD102"。您删除了第一个供应商。您创建另一个供应商,它得到 vendorid = "HYD102",因为 count = 1。您现在有两个具有相同 vendorid 的供应商。使用我的方法,每个 vendorid 总是比该城市中的最后一个高 1。而且他们从 001 开始,这不会让人觉得那个城市已经有 100 家其他供应商!
  • 还有一点,在第二行的方法中,它应该是 "last_vendorid_number = last_vendorid.vendorid.scan(/\d+$/).first.to_i" 。您错过了 vendorid。它现在工作正常。再次感谢。
  • 啊,是的,对不起。实际上,我会与您的建议稍有不同,如果找不到供应商,它将中断。我已经编辑了我的答案。
猜你喜欢
  • 2019-10-05
  • 2020-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多