Conditional validations can be used when a validation needs to be run only if a condition is satisfied. This can be implemented in many ways, a few of which we will discuss in this article.
Let’s assume we have a post model in our Rails application, and a post can be published by registered users and guests.
1
2
3
4
rails new conditional_validation
rails generate model User name user_type
rails generate model Post title body:text user:belongs_to
rails db:create db:migrate
Now add validations.
Using a symbol with :if and :unless
Make sure your post.rb looks like this:
1
2
3
4
5
6
7
8
class Post < ApplicationRecord
validates :body, length: { maximum: 100 }, if: :guest_user?
belongs_to :user
def guest_user?
user.user_type == "guest"
end
end
Test your implementation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
rails console
User.create(name: "John", user_type: "guest")
User.create(name: "Michael", user_type: "member")
user = User.first
post = Post.create(title: "A post with characters less than 100", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do.", user_id: user.id)
# This example will not pass validation as the number of characters is above 100 and user_type is guest.
post2 = Post.create(title: "A post with characters greater than 100", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
t labore et dolore magna aliqua.", user_id: user.id)
post2.valid?
=> false
post2.errors
=> #<ActiveModel::Errors:0x00007fd68821d908 @base=#<Post id: nil, title: "A post with characters greater than 100", body: "Lorem ipsum dolor sit amet, consectetur adipiscing...", user_id: 1, created_at: nil, updated_at: nil>, @messages={:body=>["is too long (maximum is 100 characters)"]}, @details={:body=>[{:error=>:too_long, :count=>100}]}>
# This example will create the post above 100 characters, as the user_type is a member.
user = User.last
post2 = Post.create(title: "A post with characters greater than 100", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
t labore et dolore magna aliqua.", user_id: user.id)
Using a Proc with :if and :unless
Make sure your post.rb looks like this:
1
2
3
4
5
class Post < ApplicationRecord
validates :body, length: { maximum: 100 }, if: Proc.new { |p| p.user.user_type == "guest" }
belongs_to :user
end
Now test your implementation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
rails console
user = User.first
post = Post.create(title: "A post with characters greater than 100", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt u
labore et dolore magna aliqua.", user_id: user.id)
post.errors
=> #<ActiveModel::Errors:0x00007fd684e84e98 @base=#<Post id: nil, title: "A post with characters greater than 100", body: "Lorem ipsum dolor sit amet, consectetur adipiscing...", user_id: 1, created_at: nil, updated_at: nil>, @messages={:body=>["is too long (maximum is 100 characters)"]}, @details={:body=>[{:error=>:too_long, :count=>100}]}>
user = User.last
# This example will create the post above 100 characters, as the user_type is a member.
post = Post.create(title: "A post with characters greater than 100", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt u
labore et dolore magna aliqua.", user_id: user.id)
Now you can validate conditionally in your Rails applications. Happy validating!