Model Validations
When you submit a Tweet on Twitter, it has a default limit of 140 characters. But how do they check it? What if I submit a Tweet with 141 characters? How does the system catch this and reject my Tweet?
This is where Model Validations come in. Effectively, your backend API can validate any data going into your database.
Here is a list of the most common validations used:
Helper Name | Description |
---|---|
length | validates the length of the attributes' values |
presence | validates that the specified attributes are present |
absence | validates that the specified attributes are absent |
uniqueness | validates that the attribute's value is unique right before the object gets saved |
allow_blank | will let validation pass if the attribute's value is blank? |
The best way to approach this is to show you an example of how model validations are used:
class Post < ActiveRecord::Base
validates :title, :length => { maximum: 140 }, :presence => true
validates :content, :length => { maximum: 140 }, :allow_blank => true
validate :spam_free
validate :post_count
private
def post_count
count = Post.count
if count > 20
self.errors.add(:base, "Cannot posts more than 20 posts")
end
end
def spam_free
# order all the posts reverse chronologically
# get the posted time for the latest post
last_post = Post.order(:created_at).last
# goal: the user can only post after 1 minute
if Post.any? and last_post.created_at > 1.minute.ago
# if this is true, the last post was made in less 1 minute ago, so please raise an error
self.errors.add(:base, "Cannot post within 1 minute")
end
end
end
Let's example line by line.
validates :title, :length => { maximum: 140 }, :presence => true
title
attribute can have a maximum 140 characters;title
attribute must be present in new record- record will not be saved if the
title
attribute is missing or exceed 140 characters
validates :content, :length => { maximum: 140 }, :allow_blank => true
content
attribute can have a maximum 140 characters but can be left blank
We use the validates
helper for attributes that are already defined in the database. We can call these default validators by Rails.
Now, what if we want to write custom validators? Well, in this case, we will use the validate
method followed by the name of the custom method.
validate :spam_free
- In this case,
spam_free
is a custom method, so we need to examine what's defined in thespam_free
method.
def spam_free
# order all the posts reverse chronologically
# get the posted time for the latest post
last_post = Post.order(:created_at).last
# goal: the user can only post after 1 minute
if Post.any? and last_post.created_at > 1.minute.ago
# if this is true, the last post was made in less 1 minute ago, so please raise an error
self.errors.add(:base, "Cannot post within 1 minute")
end
end
- We found the latest post (ordered by created_at time)
- We make sure the latest post was made at least one minute ago
- This way, we are rate limiting the frequency of new posts to 1 minute per new post
- If the latest post was made less than 1 minute ago, the API will not create a new record
Likewise, let's examine the post_count
method for custom validations.
def post_count
count = Post.count
if count > 20
self.errors.add(:base, "Cannot posts more than 20 posts")
end
end
- We make sure there can only be 20 posts existing by counting the number of records of Post
- Obviously, this validator is unreasonable in a real product
So, when do we use default validators vs custom validators? When your validation logic is complex and requires a custom method to work, then you should use custom validators. Otherwise, default validators will often satisfy your needs.
There's a huge documentation on all model validations by Rails.
Reference: