Rails - 强制字段大写并唯一验证

tkr*_*car 10 validation activerecord ruby-on-rails ruby-on-rails-3

机场有四个字母的ICAO代码.按照惯例,它们总是大写的.我正在创建一个用于接收用户输入的表单,但是此表单需要能够以大小写混合的形式接受用户输入,并防止它们创建欺骗.

:uniqueness当然,默认情况下区分大小写.我想出了如何在保存之前将用户的输入转换为大写,但问题是这似乎是后验证,而不是预验证.

例如,如果已经有ICAO的机场KLAX,用户可以输入klax,它将被验证为唯一,然后转换为大写并存储,从而产生重复.

这是我目前的型号代码.

class Airport < ActiveRecord::Base
  validates :icao, :name, :lat, :lon, :presence => true
  validates :icao, :uniqueness => true

  before_save :uppercase_icao

  def uppercase_icao
    icao.upcase!
  end
end
Run Code Online (Sandbox Code Playgroud)

Xav*_*olt 10

或者略有不同:写一个setter icao,将其抛出的任何内容转换为大写:

def icao=(val)
    self[:icao] = val.upcase
end
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用常规唯一性验证(在数据库中使用唯一索引进行备份).甚至可能会在查找过程中使数据库更容易一些,因为它不再需要担心不区分大小写的比较.

希望这可以帮助!


Wil*_*Ayd 7

试试这个:

validates :icao, :uniqueness => { :case_sensitive => false }
Run Code Online (Sandbox Code Playgroud)

  • 或者做一个before_validation而不是before_save :) (2认同)
  • 完美,丹尼 - before_validation 正是我所需要的。 (2认同)

Fra*_*ehl 5

更新了Rails 4的答案.

class Airport < ActiveRecord::Base
  validates :icao, :name, :lat, :lon, :presence => true
  validates :icao, :uniqueness => { case_sensitive: false }

  def icao=(val)
    write_attribute :icao, val.upcase
  end
end
Run Code Online (Sandbox Code Playgroud)


tkr*_*car 2

简单地修复了(就像 Rails 的许多问题一样) - 正如 Danny 上面指出的那样,尽管不是在他自己的答案中,所以我不能接受:),改为before_save完美before_validation修复它。