tkrajcar
tkrajcar

Reputation: 1712

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

Upvotes: 11

Views: 12181

Answers (4)

Frank Koehl
Frank Koehl

Reputation: 3186

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

Upvotes: 5

Xavier Holt
Xavier Holt

Reputation: 14619

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!

Upvotes: 12

tkrajcar
tkrajcar

Reputation: 1712

Simply fixed (as many problems with Rails are) - as Danny pointed out above, although not in his own answer so I can't accept it :), changing before_save to before_validation fixes it perfectly.

Upvotes: 2

Will Ayd
Will Ayd

Reputation: 7164

try this:

validates :icao, :uniqueness => { :case_sensitive => false }

Upvotes: 8

Related Questions