Chris
Chris

Reputation: 6246

Decisions based on ActiveRecord validation errors

I'm very new to rails and am wondering what the best way to do this is:

I have a controller creating a record in the database.

If a specific validation error occurs I want to set a flag, and I can't see a good way to accomplish this with the rails patterns I am familiar with.

The models validation that I want to detect is:

validates_uniqueness_of :title

My controller is doing this:

fcs = Entity.create(:title => text)

When the above error fails I have an ActiveModel errors collection to work with.

How should I go about reliably setting a flag to indicate programatically that the title has been taken?

So far I've considered

fcs.errors.messages.has_key?(:title)

But this will return true if title has failed for some other reason. So I would need something more like:

fcs.errors.messages[:title]==["has already been taken"]

But that would be a maintenance headache and would also be broken by different locales...

So does anyone know how this should be done with RoR?

Thanks for any advice

edit: Example usage of proposed flag "is_title_duplicated":

if(! fcs.errors.empty?)
      json['success']=false
      json['errors']=fcs.errors.full_messages
      json['title_was_duplicate'] = is_title_duplicated
      render :json => json

...

Upvotes: 0

Views: 329

Answers (2)

David
David

Reputation: 2331

I recommend adding a method to your model class to detect uniqueness.

class Entity < ActiveRecord::Base
  def unique_title?
    Entity.where(:title => title).count > 0
  end
end

Of course, this would mean that you're running that query twice (once for the validates_uniqueness_of and once for unique_title?). I prefer readability over performance as long as the performance is acceptable. If the performance is not acceptable, you still have options. You can re-use unique_title? in your own custom validation and cache the result.

class Entity < ActiveRecord::Base
  validate :title_must_be_unique

  def unique_title?
    # you may want to unset @unique_title when title changes
    if @unique_title.nil?
      @unique_title = Entity.where(:title => title).count > 0
    end
    @unique_title
  end

  private

  def title_must_be_unique
    unless unique_title?
      errors.add(:title, I18n.t("whatever-the-key-is-for-uniqueness-errors"))
    end
  end
end

Upvotes: 2

CambridgeMike
CambridgeMike

Reputation: 4622

Do you mean set a flag on the record? Whenever a validation fails the record is not saved to the database

If you just mean setting the error message, you don't have to. Rails will automatically set fsc.erros to be a hash that looks like {:title => "title has already been taken"}. You can specify that message by passing :message to your validation.

Also, you can internationalize the messages by using l18n. Just edit the yaml file as described here: http://guides.rubyonrails.org/i18n.html#configure-the-i18n-module

Upvotes: 1

Related Questions