【问题标题】:Rails: How can I validate my records so that no two records are the same?Rails:如何验证我的记录以确保没有两条记录是相同的?
【发布时间】:2013-07-04 00:17:52
【问题描述】:

我一直在尝试让validates_uniqueness_of 为我的数据库工作。我从 CSV 文件中提取记录,并且我想确保将它们全部记录下来,但是当我下次检查时,如果它们只是重复的,我不想再次保存它们。

示例对象

PlayerStats {session_date, uniform_number, last_name, first_name, throws, throws_caught, throws_dropped, intercepted_throws, defended_throws }

示例记录

2013-01-01, 11A, Jacobsen, Mike, 11, 4, 7, 0 0
2013-01-01, 11A, Jacobsen, Mike, 0, 0, 0, 2, 1

我想保留这两个记录,但是当我尝试像这样进行验证时...

validates_uniqueness_of :uniform_number, :scope => [:session_date, :last_name]

这只会保留例如第一条记录,而将第二条记录视为重复。 我希望它在第二条记录通过保存尝试时也会保存第二条记录。

【问题讨论】:

    标签: ruby-on-rails validation csv rails-activerecord


    【解决方案1】:

    问题是您只验证三个字段的唯一性,而不是所有字段。您应该将所有字段添加到:scope。但是,如果您有一个包含太多行的表,那将不会有很好的性能。我建议您从要验证其唯一性的所有字段中生成一个令牌,并在令牌上添加唯一性验证。走这条路,您必须在表中再添加一列来存储计算的令牌。不要忘记在列上添加唯一索引以获得最佳性能。之后,以下应该可以解决问题:

    before_validate :generate_unique_token
    
    # assuming you named your slug column `unique_token`
    validates :unique_token, uniqueness: true
    
    private
    # add all fields you want to validate uniqueness on
    UNIQUE_FIELDS = [:uniform_number, :session_date, :more_fields] 
    def generate_unique_token
      return if self.unique_token.present?
      token_string = ''
    
      # additional comma is to ensure that [1, 10]  and [11, 0] don't get treated as same input
      UNIQUE_FIELDS.each {|field| token_string << self.send(field).to_s << ','} 
    
      self.unique_token = token_string
    end
    

    这个字符串可以变大,但你不会得到任何错误的冲突。如果你想控制生成令牌的大小,你可以这样做:

    def generate_unique_token
      token_string = ''
      UNIQUE_FIELDS.each {|field| token_string << self.send(field).to_s << ','} 
      self.unique_token = compress_token(token_string)
    end
    
    def compress_token(token_string)
      # you can further compress the token by encoding it in base 62/64
      ::Digest::SHA256.hexdigest(token_string)
    end
    

    但请注意,后面的解决方案可能会出现罕见的错误碰撞。

    【讨论】:

    • 试过你的方法,但似乎没有任何东西被插入到数据库中,所以我现在正在尝试调试它。此外,我曾尝试将所有字段都放入范围,但由于某种原因之前不起作用......不知道为什么。感谢您的帮助!
    • 不确定我真正改变了什么,但看起来正在使用你的方法。也非常感谢您的解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多