Extract ExceptionMessageFinder from AllowValueMatcher

* Replaces repeated conditional with polymorphism
This commit is contained in:
Joe Ferris 2012-09-12 20:41:43 -04:00
parent 3dbf5d4f0d
commit 87327c225a
5 changed files with 181 additions and 68 deletions

View File

@ -1,6 +1,7 @@
require 'shoulda/matchers/active_model/helpers'
require 'shoulda/matchers/active_model/validation_matcher'
require 'shoulda/matchers/active_model/validation_message_finder'
require 'shoulda/matchers/active_model/exception_message_finder'
require 'shoulda/matchers/active_model/allow_value_matcher'
require 'shoulda/matchers/active_model/ensure_length_of_matcher'
require 'shoulda/matchers/active_model/ensure_inclusion_of_matcher'

View File

@ -29,7 +29,7 @@ module Shoulda # :nodoc:
def initialize(*values)
@values_to_match = values
@strict = false
@message_finder_factory = ValidationMessageFinder
@options = {}
end
@ -44,7 +44,7 @@ module Shoulda # :nodoc:
end
def strict
@strict = true
@message_finder_factory = ExceptionMessageFinder
self
end
@ -66,13 +66,7 @@ module Shoulda # :nodoc:
end
def description
base = "allow #{@attribute} to be set to #{allowed_values}"
if strict?
"strictly #{base}"
else
message_finder.allow_description(allowed_values)
end
message_finder.allow_description(allowed_values)
end
private
@ -82,19 +76,7 @@ module Shoulda # :nodoc:
end
def has_messages?
if strict?
has_exception_message?
else
message_finder.has_messages?
end
end
def has_exception_message?
@instance.valid?
false
rescue ::ActiveModel::StrictValidationFailed => exception
@strict_exception = exception
true
message_finder.has_messages?
end
def errors_for_attribute_match?
@ -106,19 +88,7 @@ module Shoulda # :nodoc:
end
def errors_for_attribute
if strict?
[strict_exception_message]
else
message_finder.messages
end
end
def strict_exception_message
@strict_exception.message
end
def strict?
@strict
message_finder.messages
end
def errors_match_regexp?
@ -139,27 +109,11 @@ module Shoulda # :nodoc:
end
def error_source
if strict?
'exception'
else
message_finder.source_description
end
message_finder.source_description
end
def error_description
if strict?
exception_description
else
message_finder.messages_description
end
end
def exception_description
if @strict_exception
strict_exception_message
else
'no exception'
end
message_finder.messages_description
end
def allowed_values
@ -181,19 +135,7 @@ module Shoulda # :nodoc:
end
def default_expected_message
if strict?
default_full_message
else
message_finder.expected_message_from(default_attribute_message)
end
end
def default_full_message
"#{human_attribute_name} #{default_attribute_message}"
end
def human_attribute_name
@instance.class.human_attribute_name(@attribute)
message_finder.expected_message_from(default_attribute_message)
end
def default_attribute_message
@ -209,7 +151,7 @@ module Shoulda # :nodoc:
end
def message_finder
@message_finder ||= ValidationMessageFinder.new(@instance, @attribute)
@message_finder ||= @message_finder_factory.new(@instance, @attribute)
end
end
end

View File

@ -0,0 +1,58 @@
module Shoulda
module Matchers
module ActiveModel
# Finds message information from exceptions thrown by #valid?
class ExceptionMessageFinder
def initialize(instance, attribute)
@instance = instance
@attribute = attribute
end
def allow_description(allowed_values)
"doesn't raise when #{@attribute} is set to #{allowed_values}"
end
def messages_description
if has_messages?
messages.join
else
'no exception'
end
end
def has_messages?
messages.any?
end
def messages
@messages ||= validate_and_rescue
end
def source_description
'exception'
end
def expected_message_from(attribute_message)
"#{human_attribute_name} #{attribute_message}"
end
private
def validate_and_rescue
@instance.valid?
[]
rescue ::ActiveModel::StrictValidationFailed => exception
[exception.message]
end
def human_attribute_name
@instance.class.human_attribute_name(@attribute)
end
end
end
end
end

View File

@ -107,7 +107,7 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher do
it "describes itself" do
allow_value("xyz").for(:attr).strict.description.
should == 'strictly allow attr to be set to "xyz"'
should == %{doesn't raise when attr is set to "xyz"}
end
it "provides a useful negative failure message" do

View File

@ -0,0 +1,112 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::ExceptionMessageFinder do
if Rails::VERSION::STRING.to_f >= 3.2
context '#allow_description' do
it 'describes its attribute' do
finder = build_finder(:attribute => :attr)
description = finder.allow_description('allowed values')
description.should == "doesn't raise when attr is set to allowed values"
end
end
context '#expected_message_from' do
it 'returns the message with the attribute name prefixed' do
finder = build_finder(:attribute => :attr)
message = finder.expected_message_from('some message')
message.should == 'Attr some message'
end
end
context '#has_messages?' do
it 'has messages when some validations fail' do
finder = build_finder(:format => /abc/, :value => 'xyz')
result = finder.has_messages?
result.should be_true
end
it 'has no messages when all validations pass' do
finder = build_finder(:format => /abc/, :value => 'abc')
result = finder.has_messages?
result.should be_false
end
end
context '#messages' do
it 'returns errors for the given attribute' do
finder = build_finder(
:attribute => :attr,
:format => /abc/,
:value => 'xyz'
)
messages = finder.messages
messages.should == ['Attr is invalid']
end
end
context '#messages_description' do
it 'describes errors for the given attribute' do
finder = build_finder(
:attribute => :attr,
:format => /abc/,
:value => 'xyz'
)
description = finder.messages_description
description.should == 'Attr is invalid'
end
it 'describes errors when there are none' do
finder = build_finder(:format => /abc/, :value => 'abc')
description = finder.messages_description
description.should == 'no exception'
end
end
context '#source_description' do
it 'describes the source of its messages' do
finder = build_finder
description = finder.source_description
description.should == 'exception'
end
end
end
def build_finder(arguments = {})
arguments[:attribute] ||= :attr
instance = build_instance_validating(
arguments[:attribute],
arguments[:format] || /abc/,
arguments[:value] || 'abc'
)
Shoulda::Matchers::ActiveModel::ExceptionMessageFinder.new(
instance,
arguments[:attribute]
)
end
def build_instance_validating(attribute, format, value)
model_class = define_model(:example, attribute => :string) do
attr_accessible attribute
validates_format_of attribute, :with => format, :strict => true
end
model_class.new(attribute => value)
end
end