Antonio
Antonio

Reputation: 751

ActiveRecord, validates_uniqueness_of :name not catching non-uniquness if I have a capitalize method

I have a simple capitalize method so that when user submits a new band in the band page it returns it with the first letter capitalized. Inside my Band class I also have a validates_uniqueness_of :band_name to see if there is already a band with the same entry. See code below:

  class Band < ActiveRecord::Base
    has_and_belongs_to_many :venues
    validates :band_name, :presence => true
    before_save :title_case
    validates_uniqueness_of :band_name

  private

    def title_case
      self.band_name.capitalize!
    end

  end

So if I type in someband, it creates it and displays it as Someband. If I type someband again, ActiveRecord sees it as unique and I'll get another Someband. The only way it works is if I type Someband. How would I remedy this situation?

Upvotes: 2

Views: 102

Answers (3)

EugZol
EugZol

Reputation: 6555

You can use attribute setter instead of before_save callback to capitalize your value without postponing.

def band_name=(value)
  self['band_name'] = value && value.mb_chars.capitalize
end

Upvotes: 0

Levi
Levi

Reputation: 175

The reason your code doesn't work is because validations happen before the before_save callbacks are triggered. Check out the list of ActiveRecord::Callbacks for the order in which things are called.

MZaragoza's answer is a great option for making your validation work regardless of what casing your users might enter. It will prevent things like "someband" and "SomeBand" from being added. I recommend including that as part of your solution.

Another option very similar to the code you already have is to switch to using the before_validation callback:

before_validation :title_case

I highly recommend using the before_validation callbacks instead of before_save callbacks whenever data changes that may be relevant to your validation rules, regardless of what other changes you make. That ensures that you are checking that actual state of the model that you plan to save to the database.

Upvotes: 1

MZaragoza
MZaragoza

Reputation: 10111

I think what you want to do is this

validates_uniqueness_of :band_name, :case_sensitive :false, allow_blank: false

Take a look at http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html

:case_sensitive - Looks for an exact match. Ignored by non-text columns (true by default).

Upvotes: 5

Related Questions