Skip to content
This repository
Browse code

Extract ValidationMessageFinder from AllowValueMatcher

  • Loading branch information...
commit 3dbf5d4f0d5943ae11f7c770a172c9c71f24ac87 1 parent 96d32c2
Joe Ferris authored September 12, 2012
1  lib/shoulda/matchers/active_model.rb
... ...
@@ -1,5 +1,6 @@
1 1
 require 'shoulda/matchers/active_model/helpers'
2 2
 require 'shoulda/matchers/active_model/validation_matcher'
  3
+require 'shoulda/matchers/active_model/validation_message_finder'
3 4
 require 'shoulda/matchers/active_model/allow_value_matcher'
4 5
 require 'shoulda/matchers/active_model/ensure_length_of_matcher'
5 6
 require 'shoulda/matchers/active_model/ensure_inclusion_of_matcher'
51  lib/shoulda/matchers/active_model/allow_value_matcher.rb
@@ -71,34 +71,30 @@ def description
71 71
           if strict?
72 72
             "strictly #{base}"
73 73
           else
74  
-            base
  74
+            message_finder.allow_description(allowed_values)
75 75
           end
76 76
         end
77 77
 
78 78
         private
79 79
 
80 80
         def errors_match?
  81
+          has_messages? && errors_for_attribute_match?
  82
+        end
  83
+
  84
+        def has_messages?
81 85
           if strict?
82  
-            exception_message_matches?
  86
+            has_exception_message?
83 87
           else
84  
-            validation_messages_match?
  88
+            message_finder.has_messages?
85 89
           end
86 90
         end
87 91
 
88  
-        def exception_message_matches?
  92
+        def has_exception_message?
89 93
           @instance.valid?
90 94
           false
91 95
         rescue ::ActiveModel::StrictValidationFailed => exception
92 96
           @strict_exception = exception
93  
-          errors_for_attribute_match?
94  
-        end
95  
-
96  
-        def validation_messages_match?
97  
-          if @instance.valid?
98  
-            false
99  
-          else
100  
-            errors_for_attribute_match?
101  
-          end
  97
+          true
102 98
         end
103 99
 
104 100
         def errors_for_attribute_match?
@@ -113,7 +109,7 @@ def errors_for_attribute
113 109
           if strict?
114 110
             [strict_exception_message]
115 111
           else
116  
-            validation_messages_for_attribute
  112
+            message_finder.messages
117 113
           end
118 114
         end
119 115
 
@@ -121,15 +117,6 @@ def strict_exception_message
121 117
           @strict_exception.message
122 118
         end
123 119
 
124  
-        def validation_messages_for_attribute
125  
-          if @instance.errors.respond_to?(:[])
126  
-            errors = @instance.errors[@attribute]
127  
-          else
128  
-            errors = @instance.errors.on(@attribute)
129  
-          end
130  
-          Array.wrap(errors)
131  
-        end
132  
-
133 120
         def strict?
134 121
           @strict
135 122
         end
@@ -155,7 +142,7 @@ def error_source
155 142
           if strict?
156 143
             'exception'
157 144
           else
158  
-            'errors'
  145
+            message_finder.source_description
159 146
           end
160 147
         end
161 148
 
@@ -163,7 +150,7 @@ def error_description
163 150
           if strict?
164 151
             exception_description
165 152
           else
166  
-            validation_error_description
  153
+            message_finder.messages_description
167 154
           end
168 155
         end
169 156
 
@@ -175,14 +162,6 @@ def exception_description
175 162
           end
176 163
         end
177 164
 
178  
-        def validation_error_description
179  
-          if @instance.errors.empty?
180  
-            "no errors"
181  
-          else
182  
-            "errors: #{pretty_error_messages(@instance)}"
183  
-          end
184  
-        end
185  
-
186 165
         def allowed_values
187 166
           if @values_to_match.length > 1
188 167
             "any of [#{@values_to_match.map(&:inspect).join(', ')}]"
@@ -205,7 +184,7 @@ def default_expected_message
205 184
           if strict?
206 185
             default_full_message
207 186
           else
208  
-            default_attribute_message
  187
+            message_finder.expected_message_from(default_attribute_message)
209 188
           end
210 189
         end
211 190
 
@@ -228,6 +207,10 @@ def default_attribute_message
228 207
         def model_name
229 208
           @instance.class.to_s.underscore
230 209
         end
  210
+
  211
+        def message_finder
  212
+          @message_finder ||= ValidationMessageFinder.new(@instance, @attribute)
  213
+        end
231 214
       end
232 215
     end
233 216
   end
69  lib/shoulda/matchers/active_model/validation_message_finder.rb
... ...
@@ -0,0 +1,69 @@
  1
+module Shoulda
  2
+  module Matchers
  3
+    module ActiveModel
  4
+
  5
+      # Finds message information from a model's #errors method.
  6
+      class ValidationMessageFinder
  7
+        include Helpers
  8
+
  9
+        def initialize(instance, attribute)
  10
+          @instance = instance
  11
+          @attribute = attribute
  12
+        end
  13
+
  14
+        def allow_description(allowed_values)
  15
+          "allow #{@attribute} to be set to #{allowed_values}"
  16
+        end
  17
+
  18
+        def expected_message_from(attribute_message)
  19
+          attribute_message
  20
+        end
  21
+
  22
+        def has_messages?
  23
+          errors.present?
  24
+        end
  25
+
  26
+        def source_description
  27
+          'errors'
  28
+        end
  29
+
  30
+        def messages_description
  31
+          if errors.empty?
  32
+            "no errors"
  33
+          else
  34
+            "errors: #{pretty_error_messages(validated_instance)}"
  35
+          end
  36
+        end
  37
+
  38
+        def messages
  39
+          Array.wrap(messages_for_attribute)
  40
+        end
  41
+
  42
+        private
  43
+
  44
+        def messages_for_attribute
  45
+          if errors.respond_to?(:[])
  46
+            errors[@attribute]
  47
+          else
  48
+            errors.on(@attribute)
  49
+          end
  50
+        end
  51
+
  52
+        def errors
  53
+          validated_instance.errors
  54
+        end
  55
+
  56
+        def validated_instance
  57
+          @validated_instance ||= validate_instance
  58
+        end
  59
+
  60
+        def validate_instance
  61
+          @instance.valid?
  62
+          @instance
  63
+        end
  64
+      end
  65
+
  66
+    end
  67
+  end
  68
+end
  69
+
105  spec/shoulda/active_model/validation_message_finder_spec.rb
... ...
@@ -0,0 +1,105 @@
  1
+require 'spec_helper'
  2
+
  3
+describe Shoulda::Matchers::ActiveModel::ValidationMessageFinder do
  4
+  context '#allow_description' do
  5
+    it 'describes its attribute' do
  6
+      finder = build_finder(:attribute => :attr)
  7
+
  8
+      description = finder.allow_description('allowed values')
  9
+
  10
+      description.should == 'allow attr to be set to allowed values'
  11
+    end
  12
+  end
  13
+
  14
+  context '#expected_message_from' do
  15
+    it 'returns the message as-is' do
  16
+      finder = build_finder
  17
+
  18
+      message = finder.expected_message_from('some message')
  19
+
  20
+      message.should == 'some message'
  21
+    end
  22
+  end
  23
+
  24
+  context '#has_messages?' do
  25
+    it 'has messages when some validations fail' do
  26
+      finder = build_finder(:format => /abc/, :value => 'xyz')
  27
+
  28
+      result = finder.has_messages?
  29
+
  30
+      result.should be_true
  31
+    end
  32
+
  33
+    it 'has no messages when all validations pass' do
  34
+      finder = build_finder(:format => /abc/, :value => 'abc')
  35
+
  36
+      result = finder.has_messages?
  37
+
  38
+      result.should be_false
  39
+    end
  40
+  end
  41
+
  42
+  context '#messages' do
  43
+    it 'returns errors for the given attribute' do
  44
+      finder = build_finder(:format => /abc/, :value => 'xyz')
  45
+
  46
+      messages = finder.messages
  47
+
  48
+      messages.should == ['is invalid']
  49
+    end
  50
+  end
  51
+
  52
+  context '#messages_description' do
  53
+    it 'describes errors for the given attribute' do
  54
+      finder = build_finder(
  55
+        :attribute => :attr,
  56
+        :format => /abc/,
  57
+        :value => 'xyz'
  58
+      )
  59
+
  60
+      description = finder.messages_description
  61
+
  62
+      description.should == 'errors: ["attr is invalid (\"xyz\")"]'
  63
+    end
  64
+
  65
+    it 'describes errors when there are none' do
  66
+      finder = build_finder(:format => /abc/, :value => 'abc')
  67
+
  68
+      description = finder.messages_description
  69
+
  70
+      description.should == 'no errors'
  71
+    end
  72
+  end
  73
+
  74
+  context '#source_description' do
  75
+    it 'describes the source of its messages' do
  76
+      finder = build_finder
  77
+
  78
+      description = finder.source_description
  79
+
  80
+      description.should == 'errors'
  81
+    end
  82
+  end
  83
+
  84
+  def build_finder(arguments = {})
  85
+    arguments[:attribute] ||= :attr
  86
+    instance = build_instance_validating(
  87
+      arguments[:attribute],
  88
+      arguments[:format] || /abc/,
  89
+      arguments[:value] || 'abc'
  90
+    )
  91
+    Shoulda::Matchers::ActiveModel::ValidationMessageFinder.new(
  92
+      instance,
  93
+      arguments[:attribute]
  94
+    )
  95
+  end
  96
+
  97
+  def build_instance_validating(attribute, format, value)
  98
+    model_class = define_model(:example, attribute => :string) do
  99
+      attr_accessible attribute
  100
+      validates_format_of attribute, :with => format
  101
+    end
  102
+
  103
+    model_class.new(attribute => value)
  104
+  end
  105
+end

0 notes on commit 3dbf5d4

Please sign in to comment.
Something went wrong with that request. Please try again.