While reading a code or while doing code review, I have see many times people write a test cases for model validation like this,
Before
Means we can take a benifits from it. So improved test case code is,
After
Before
References :
http://api.rubyonrails.org/classes/ActiveModel/Errors.html
activemodel/lib/active_model/validations/presence.rb
activemodel/lib/active_model/locale/en.yml
Before
# app/models/post.rb class Post < ActiveRecord::Base validates :title, presence: true end
# test/models/post_test.rb test "should have the necessary required validators" do post = Post.new assert_not post.valid? assert post.errors.has_key(:title) # or some times assert_equal ["can't be blank"], post.errors.messages[:title] endAnd if same attribute has more than one validation then,
# app/models/post.rb
class Post < ActiveRecord::Base
validates :title, presence: true, length: { in: 10..60 }
end
Most of the people do,
test "should have the necessary required validators" do post = Post.new assert_not post.valid? assert_equal ["can't be blank", "is too short (minimum is 10 characters)"], post.errors.messages[:title] endI think instead we can use symbol for it. Rails internally uses I18n locale support for error messages. For more details have a quick look on reference links provided below.
Means we can take a benifits from it. So improved test case code is,
After
test "should have the necessary required validators" do
post = Post.new
assert_not post.valid?
assert post.errors.added? :title, :blank
assert post.errors.added? :title, :too_short, { count: 20 }
end
While for custom validate method, you can use same approch by defining new key. Key can be any valid symbol.
Before
class Post < ActiveRecord::Base
has_many :tags
validates :title, presence: true
validate :validate_tags_count
private
def validate_tags_count
errors.add(:tags, "required alteast 2 tags") if tags.reject(&:marked_for_destruction?).count < 2
end
end
After
class Post < ActiveRecord::Base
has_many :tags
validates :title, presence: true
validate :validate_tags_count
private
def validate_tags_count
errors.add(:tags, :required, count: 2) if tags.reject(&:marked_for_destruction?).count < 2
end
end
test "should have the necessary required validators" do
post = Post.new
assert_not post.valid?
assert post.errors.added? :tags, :required, { count: 2 }
end
#config/locales/en.yml
# Globally for all models
en:
errors:
messages:
required: "minimum %{count} tags required"
or
#config/locales/en.yml
# only to post models
en:
activerecord:
errors:
models:
post:
attributes:
tags:
required: "minimum %{count} tags required"
Same concept will work on rails 5 as well. Tested with rails 5.0.0.beta4.
References :
http://api.rubyonrails.org/classes/ActiveModel/Errors.html
activemodel/lib/active_model/validations/presence.rb
activemodel/lib/active_model/locale/en.yml