Today, I am writing the blog post with my late apologization. Sorry to all of my readers and followers for not writing any good posts on the last couple of days. I am passing very busy time for the office project as well as my Grad school. By the way, I started my new career at IOU Finance Inc. as Software Engineer. The company has a nice, secure and scalable financial platform based on Ruby on Rails (Rails framework version 3) where right now I am working on. Whatever, last of couple of days I wrote several rails 3 validator in order to clean up some historical data. Now, I will talk about how easily you can write your own customized validator to validate your model data.
In Rails 3, ActiveRecord comes with some modules likes Serialization, Errors, Dirty, Callbacks, and validations. There are basically two types of validator modules are included in ActiveRecord. One is ActiveModel::Validations which takes care validation in the model layer, and another one is ActiveRecord::Validations works as database layer validations likes uniqueness, associate. This is all about the basic idea. For now, writing a custom validation you will have to extend it from ActiveModel::Validator or from ActiveModel::EachValidator. Here again, ActiveModel::Validator works with one record and ActiveModel::EachValidator works with attributes. I will show the example each of them.
Let’s start with the first one, which extends from ActiveModel::Validator and takes a record to validate. Create a file with your validator name, for example: IsWordExistsValidator under the lib directory of your application. One thing is that needs to be mentioned here you will have to implement a validate method.
In directory, it will be look like as follows
/lib/is_word_exists_validator.rb
# lib/is_word_exists_validator.rb class IsWordExistsValidator < ActiveModel::Validator WORDS = %w(john robert) def validate(record) unless WORDS.include?record.name record.errors[:name] << "It's not a valid string." end end end |
Now, in your model class just add the following lines..
class User < ActiveRecord::Base validates :name, is_word_exists: true end |
If your model doesn’t extend from ActiveRecord, then you will have to include the validator manually.
class User include ActiveModel::Validations validates_with IsWordExistsValidator end |
Now, I will show the vlaidator with ActiveModel::EachValidator which takes the attributes: record, attribute, value. Again your have to create file as same as validator class name under the lib directory. In this case, keep it in your mind that you must implement the validate_each method.
# lib/is_word_exists_validator.rb class IsWordExistsValidator < ActiveModel::EachValidator WORDS = %w(john robert) # it accepts custom error message def validate_each(record, attribute, value) record.errors[attribute] << (options[:message] || "It's not a valid string.") unless WORDS.include?(value) end end |
Add the validator in your model…
class User < ActiveRecord::Base validates :name, :presence => true, :is_word_exists => true end |
You pass something :message => “some error message”, then validator will print this message instead the default one.
You can also use this validator in following way..
user = User.new(name: 'john') user.valid? #=> true |
Done. You can write your own Rails validator right away.