Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding a validation error with a before_save callback or custom validator?

I have a model Listing that belongs_to :user. Alternatively, User has_many :listings. Each listing has a category field that classifies it (dogs, cats, etc). The User also has a boolean field called is_premium.

Here is how I am validating the category...

validates_format_of :category,
                    :with => /(dogs|cats|birds|tigers|lions|rhinos)/,
                    :message => 'is incorrect'

Let's say I only want to allow premium users to be able to add tigers, lions, and rhinos. How would I go about this? Would it be best to do it in a before_save method?

before_save :premium_check

def premium_check
  # Some type of logic here to see if category is tiger, lion, or rhino.
  # If it is, then check if the user is premium. If it's not, it doesn't matter.
  # If user isn't premium then add an error message.
end

Thanks in advance!

like image 320
gbdev Avatar asked Oct 23 '13 14:10

gbdev


People also ask

What does err validation mean?

Validations errors are errors when users do not respond to mandatory questions. A validation error occurs when you have validation/response checking turned on for one of the questions and the respondent fails to answer the question correctly (for numeric formatting , required response).

Can we save an object in the DB if its validation do not pass?

Some methods will trigger validations, but some will not. This means that it's possible to save an object in the database in an invalid state if you aren't careful. The following methods trigger validations, and will save the object to the database only if the object is valid: create.

What is validation in Ruby?

Validations are used to ensure that only valid data is saved into your database. For example, it may be important to your application to ensure that every user provides a valid email address and mailing address. Model-level validations are the best way to ensure that only valid data is saved into your database.


3 Answers

class Listing < ActiveRecord::Base    
  validate :premium_category

  private

  def premium_category
    if !user.is_premium && %w(tigers lions rhinos).include?(category))
      errors.add(:category, "not valid for non premium users")
    end
  end
end
like image 200
usha Avatar answered Sep 28 '22 10:09

usha


If you want to add validation errors doing the before_save you could raise an exception then add the error in the controller like this:

class Listing < ActiveRecord::Base    
  before_save :premium_category

  private

  def premium_category
    if !user.is_premium && %w(tigers lions rhinos).include?(category))
      raise Exceptions::NotPremiumUser, "not valid for non premium users"
    end
  end
end

Then in your controller do something like:

begin 
    @listing.update(listing_params)
    respond_with(@listing)
rescue Exceptions::NotPremiumUser => e
      @listing.errors.add(:base, e.message)
      respond_with(@listing)    
end

Then in your /lib folder add a class like this:

module Exceptions
  class NotPremiumUser < StandardError; end
end

But in your case I think using the validate method is a better solution.

Cheers,

like image 45
Eric Avatar answered Sep 28 '22 10:09

Eric


You can use validates_exclusion_of:

validates :category, :exclusion => {
  :in => ['list', 'of', 'invalid'],
  :message => 'must not be premium category',
  :unless => :user_is_premium?
}

protected

def user_is_premium?
  self.user.premium?
end
like image 40
kristinalim Avatar answered Sep 28 '22 08:09

kristinalim