Understanding Rails Custom Validations

Validations are like gatekeepers for your models.
  • Database constraints make the validation mechanisms database-dependent and can make testing and maintenance difficult. However, if your database is used by other applications too, it may be a nice idea to use some constraints at the database level. Adding to that, database-level validations can safely handle some things (eg: uniqueness in heavily-used tables) that can be difficult to implement otherwise.
  • Client-side validations can be useful, but are generally capricious if used alone. If they are implemented using JavaScript, they may be bypassed if JavaScript is turned off in the user’s browser.
  • Controller-level validations can be tempting to use, but often become unwieldy and difficult to test and maintain. Controllers should be leaner, as its easy to maintain for a long run.
  • Use a custom method to perform the validation.
  • Creating a helper validator class
  • Create an EachValidator class which validates a particular attribute. The one, for which it has been called.
  • We want title should be of minimum length of 10 chars, and each title should contain a keyword i.e. great-article .
  • The volume of the item must be between 20 and 3000 cubic meters (ie. Volume Validation)
  • The compactness of the item cannot exceed 200 grams per cubic meters (ie. Compactness Validation)
  • No side length can be less than 15% of the largest side (ie. proportion validation).
  • Use a custom method to perform the validation.
class Item < ActiveRecord::Base  ...
validate :length_and_string_presence
validates :title, presence:true, length: { minimum: 10 }
...
private

def title_rules_adhered?
title.include?("great-article")
end
def length_and_string_presence
unless title_rules_adhered?
errors.add(:title, "must contain 'great-article'")
end
end
end
class Item < ActiveRecord::Base

validates_with CompactnessValidator

end
class CompactnessValidator << ActiveModel::Validator
def validate(record)
if record.compactness > 10
record.errors.add(:compactness, “is too high to safely dispatch”)
end
end
end
class CompactnessValidator << ActiveModel::Validator
def validate(record)
if record.compactness > 10
record.errors.add(:compactness, “is too high to safely dispatch”)
end
if record.title.length < 10
record.errors.add(:title, "length must be greater than 10")
elsif !record.title.include?("great-article")
record.errors.add(:title, "must include great-article")
end
end
end
class Item < ActiveRecord::Base
...
validates :height, :width, :depth, item_dimensions_proportion: true
...
end
class ItemDimensionsProportionValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if value < [record.width,record.height,record.depth].max * 0.15
record.errors.add(attribute, "cannot be so short as to make
the package oddly sized :(")
end
end
end

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store