Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Extract ExceptionMessageFinder from AllowValueMatcher

* Replaces repeated conditional with polymorphism
commit 87327c225a4c9d492a370fe8ee91631433145b69 1 parent 3dbf5d4
@jferris jferris authored
View
1  lib/shoulda/matchers/active_model.rb
@@ -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
76 lib/shoulda/matchers/active_model/allow_value_matcher.rb
@@ -29,7 +29,7 @@ class AllowValueMatcher # :nodoc:
def initialize(*values)
@values_to_match = values
- @strict = false
+ @message_finder_factory = ValidationMessageFinder
@options = {}
end
@@ -44,7 +44,7 @@ def with_message(message)
end
def strict
- @strict = true
+ @message_finder_factory = ExceptionMessageFinder
self
end
@@ -66,13 +66,7 @@ def negative_failure_message
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 @@ def errors_match?
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 @@ def errors_for_attribute_match?
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 @@ def expectation
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 @@ def expected_message
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 @@ def model_name
end
def message_finder
- @message_finder ||= ValidationMessageFinder.new(@instance, @attribute)
+ @message_finder ||= @message_finder_factory.new(@instance, @attribute)
end
end
end
View
58 lib/shoulda/matchers/active_model/exception_message_finder.rb
@@ -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
2  spec/shoulda/active_model/allow_value_matcher_spec.rb
@@ -107,7 +107,7 @@
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
112 spec/shoulda/active_model/exception_message_finder_spec.rb
@@ -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
+
Please sign in to comment.
Something went wrong with that request. Please try again.