ruby-on-rails - rails 检查唯一性并处理条件

标签 ruby-on-rails ruby

所以我明白我可以写

validates :column_name, uniqueness: :true

我可以测试一个字段是否是唯一的。但如果不是,则上述应用程序会抛出错误。我不想抛出错误,而是希望能够通过添加一个整数来使其唯一。

该属性称为“legacy_code”。该代码由标题措辞的第一个字母生成,并通过

调用操作
  after_create :generate_article_legacy_code

所以我写的测试是这样的

@article = FactoryGirl.create :article, title: 'Big Cheesey Pudding Yum Yum'
@article_one = FactoryGirl.create :article, title: 'Blue Chaffinches Purchased Yoko Yamamoto' 

  it "should be unique" do 
    expect(@article.legacy_code).to eq('BCPYY')
    expect(@article_one.legacy_code).to eq('BCPYY1')

  end

那么如何在文章类中实现这种功能呢?

谢谢

最佳答案

如果文章标题的首字母缩略词有多个副本怎么办?例如,假设有 3 个副本,title_acronym 在第二次或第三次查找时不会是唯一的,您最终会得到 ABC、ABC1、ABC2。那就是你想要的。但是如果标题以数字结尾,您就会发现问题。您可以有 (ABC1)、(ABC1)1、(ABC1)2 ... 等等,但是当您想要增加首字母缩略词时,如果不事先做一些工作,您将无法判断它是 1 还是 11。这会变得一团糟。

我会让标题和名为 number 的列一起唯一。所以在 Rails 4 模型中你会有这样的东西

validates :title_acronym, uniqueness: {scope: :number}

每当弹出具有相同 title_acronym 的文章时,该文章将只需要 适本地设置它自己的数字计数器。您可以在模型上创建一个名为 legacy_code 的属性,它返回您想要的这两者的联合。完整代码如下。

validates :title, presence: :true
validates :title_acronym, presence: true
validates :number, presence: true 
validates :legacy_code, presence: true
validates :title_acronym, uniqueness: {scope: :number}

before_validate :setupArticle

def setupArticle
  generate_title_acronym
  generate_number
  generate_legacy_code
end

def generate_title_acronym
  if self.title.nil?
    return nil
  end
  #Code to set the title_acronym from the title
end

def generate_number
  if self.title_acronym.nil?
    return nil
  end
  self.number = Article.where(title_acronym, title_acronym).maximum(:number) || 0
end

def generate_legacy_code
  if self.title_acronym.nil? || self.number.nil?
    return nil
  end
  if self.number == 0
     self.legacy_code = "#{self.title_acronym}"
  else
     self.legacy_code = "#{self.title_acronym}#{self.number}"
  end
end

也可以在数据库级别强制执行唯一性,但这可能不是必需的。

如果您想通过其 legacy_code 查找单个记录,则存在一个基本问题。假设有 title_acronym ABC 和另一个 title_acronym ABC1。由于这些是他们 title_acronym 的第一个,因此他们的 title_acronym 和 legacy_code 是相同的。如果还有另一篇文章的标题是首字母缩略词 ABC,则其 legacy_code 必须变为 ABC1 但这不是唯一的,因为 legacy_code 已经存在。

这意味着,如果您不能保证标题不以数字结尾,您就不能使用 legacy_code 可靠地搜索唯一记录,因为 legacy_code 本质上不会产生唯一值。您需要使用 title_acronym 和数字来搜索唯一记录。我正在假设标题可以以数字结尾,因为毕竟您是在处理文章。

如果您愿意更改 legacy_codes 的外观以获得优于它们的唯一性。您可以在 title_acronym 和数字之间添加分隔符。我在这个例子中使用了下划线。

if self.number == 0
   self.legacy_code = "#{self.title_acronym}"
else
   self.legacy_code = "#{self.title_acronym}_#{self.number}"
end

legacy_codes 现在保证是唯一的,因为它由保证唯一的部分和一个分隔符组成,但您可以添加它以达到更好的效果。

validates :legacy_code, uniqueness: :true

关于ruby-on-rails - rails 检查唯一性并处理条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25506886/

相关文章:

mysql - psql 查询中的点表示法 - 有什么区别?

ruby-on-rails - SimpleCov 与 Selenium/Rails

ruby-on-rails - 如何根据编辑模型的表单返回不同的响应

ruby-on-rails - accepts_nested_attributes_for 是否也应该正确设置关联?

ruby-on-rails - Rails - 带有自定义路由的 link_to

ruby-on-rails - "Couldn' t find User without an ID"访问相关模型

ruby - 将 2 个数组转换为 1 个哈希

ruby-on-rails - 如果条件与 &&,是否有任何性能提升

ruby - `require` 与 `gem` 方法?

ruby-on-rails - 带有 Rails 5.1 的 Redis 打破了 Rspec