Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails - force field uppercase and validate uniquely

Airports have four-letter ICAO codes. By convention, these are always uppercase. I'm creating a form for receiving user input, but this form needs to be able to accept user input in mixed case, and prevent them from creating dupes.

The default :uniqueness is case-sensitive, of course. I figured out how to transform the user's input to uppercase before it gets saved, but the problem is that this appears to be post-validation, instead of pre-validation.

For example, if there is already an Airport with ICAO of KLAX, a user can enter klax, it will get validated as unique, and then transformed to uppercase and stored, resulting in duplicates.

Here's my model code at present.

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
like image 451
tkrajcar Avatar asked Feb 22 '11 19:02

tkrajcar


3 Answers

Or a slightly different take: Write a setter for icao that converts anything thrown at it to uppercase:

def icao=(val)
    self[:icao] = val.upcase
end

And then you can use regular uniqueness validation (back it up with a unique index in your DB). Might even make things a little easier for the DB during finds, 'cause it doesn't have to worry about case-insensitive comparisons any more.

Hope this helps!

like image 184
Xavier Holt Avatar answered Oct 28 '22 10:10

Xavier Holt


try this:

validates :icao, :uniqueness => { :case_sensitive => false }
like image 8
Will Ayd Avatar answered Oct 28 '22 10:10

Will Ayd


Updated answer for 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
like image 5
Frank Koehl Avatar answered Oct 28 '22 10:10

Frank Koehl