shoulda-matchers 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +11 -0
- data/.travis.yml +13 -0
- data/Appraisals +4 -6
- data/CONTRIBUTING.md +38 -0
- data/Gemfile +8 -5
- data/Gemfile.lock +77 -41
- data/NEWS.md +32 -0
- data/README.md +84 -0
- data/Rakefile +5 -36
- data/features/rails_integration.feature +88 -0
- data/features/step_definitions/rails_steps.rb +111 -0
- data/features/support/env.rb +5 -0
- data/gemfiles/3.0.gemfile +14 -0
- data/gemfiles/3.0.gemfile.lock +142 -0
- data/gemfiles/3.1.gemfile +16 -0
- data/gemfiles/3.1.gemfile.lock +164 -0
- data/lib/shoulda/matchers/action_controller/assign_to_matcher.rb +6 -9
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +1 -3
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +10 -6
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +1 -4
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +6 -6
- data/lib/shoulda/matchers/action_controller/respond_with_content_type_matcher.rb +11 -10
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +0 -2
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +17 -14
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +24 -16
- data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +52 -15
- data/lib/shoulda/matchers/action_mailer.rb +1 -1
- data/lib/shoulda/matchers/action_mailer/{have_sent_email.rb → have_sent_email_matcher.rb} +37 -21
- data/lib/shoulda/matchers/active_model.rb +1 -0
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +9 -10
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +60 -33
- data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +0 -1
- data/lib/shoulda/matchers/active_model/helpers.rb +13 -9
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +63 -0
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +38 -8
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +1 -5
- data/lib/shoulda/matchers/active_record.rb +3 -1
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +127 -0
- data/lib/shoulda/matchers/active_record/association_matcher.rb +19 -7
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +20 -5
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +4 -10
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +3 -7
- data/lib/shoulda/matchers/active_record/query_the_database_matcher.rb +107 -0
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +111 -0
- data/lib/shoulda/matchers/integrations/rspec.rb +0 -1
- data/lib/shoulda/matchers/version.rb +1 -1
- data/shoulda-matchers.gemspec +30 -0
- data/spec/fixtures/addresses.yml +3 -0
- data/spec/fixtures/friendships.yml +0 -0
- data/spec/fixtures/posts.yml +5 -0
- data/spec/fixtures/products.yml +0 -0
- data/spec/fixtures/taggings.yml +0 -0
- data/spec/fixtures/tags.yml +9 -0
- data/spec/fixtures/users.yml +6 -0
- data/spec/shoulda/action_controller/assign_to_matcher_spec.rb +61 -0
- data/spec/shoulda/action_controller/filter_param_matcher_spec.rb +20 -0
- data/spec/shoulda/action_controller/redirect_to_matcher_spec.rb +40 -0
- data/spec/shoulda/action_controller/render_template_matcher_spec.rb +69 -0
- data/spec/shoulda/action_controller/render_with_layout_matcher_spec.rb +47 -0
- data/spec/shoulda/action_controller/respond_with_content_type_matcher_spec.rb +28 -0
- data/spec/shoulda/action_controller/respond_with_matcher_spec.rb +83 -0
- data/spec/shoulda/action_controller/route_matcher_spec.rb +65 -0
- data/spec/shoulda/action_controller/set_session_matcher_spec.rb +46 -0
- data/spec/shoulda/action_controller/set_the_flash_matcher_spec.rb +124 -0
- data/spec/shoulda/action_mailer/have_sent_email_spec.rb +293 -0
- data/spec/shoulda/active_model/allow_mass_assignment_of_matcher_spec.rb +95 -0
- data/spec/shoulda/active_model/allow_value_matcher_spec.rb +91 -0
- data/spec/shoulda/active_model/ensure_exclusion_of_matcher_spec.rb +57 -0
- data/spec/shoulda/active_model/ensure_inclusion_of_matcher_spec.rb +71 -0
- data/spec/shoulda/active_model/ensure_length_of_matcher_spec.rb +125 -0
- data/spec/shoulda/active_model/helpers_spec.rb +100 -0
- data/spec/shoulda/active_model/validate_acceptance_of_matcher_spec.rb +43 -0
- data/spec/shoulda/active_model/validate_confirmation_of_matcher_spec.rb +48 -0
- data/spec/shoulda/active_model/validate_format_of_matcher_spec.rb +38 -0
- data/spec/shoulda/active_model/validate_numericality_of_matcher_spec.rb +62 -0
- data/spec/shoulda/active_model/validate_presence_of_matcher_spec.rb +121 -0
- data/spec/shoulda/active_model/validate_uniqueness_of_matcher_spec.rb +143 -0
- data/spec/shoulda/active_record/accept_nested_attributes_for_matcher_spec.rb +84 -0
- data/spec/shoulda/active_record/association_matcher_spec.rb +449 -0
- data/spec/shoulda/active_record/have_db_column_matcher_spec.rb +185 -0
- data/spec/shoulda/active_record/have_db_index_matcher_spec.rb +88 -0
- data/spec/shoulda/active_record/have_readonly_attributes_matcher_spec.rb +46 -0
- data/spec/shoulda/active_record/query_the_database_matcher_spec.rb +45 -0
- data/spec/shoulda/active_record/serialize_matcher_spec.rb +81 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/support/model_builder.rb +149 -0
- metadata +211 -60
- data/CONTRIBUTION_GUIDELINES.rdoc +0 -10
- data/README.rdoc +0 -80
@@ -11,6 +11,7 @@ module Shoulda # :nodoc:
|
|
11
11
|
# it { should have_sent_email.with_part('text/html', /HTML spam/) }
|
12
12
|
# it { should have_sent_email.with_subject(/spam/).
|
13
13
|
# from('do-not-reply@example.com').
|
14
|
+
# reply_to('reply-to-me@example.com').
|
14
15
|
# with_body(/spam/).
|
15
16
|
# to('myself@me.com') }
|
16
17
|
#
|
@@ -43,6 +44,12 @@ module Shoulda # :nodoc:
|
|
43
44
|
self
|
44
45
|
end
|
45
46
|
|
47
|
+
def reply_to(reply_to = nil, &block)
|
48
|
+
@reply_to = reply_to
|
49
|
+
@reply_to_block = block
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
46
53
|
def with_body(body = nil, &block)
|
47
54
|
@body = body
|
48
55
|
@body_block = block
|
@@ -94,21 +101,9 @@ module Shoulda # :nodoc:
|
|
94
101
|
|
95
102
|
def matches?(subject)
|
96
103
|
normalize_blocks
|
97
|
-
::ActionMailer::Base.deliveries.
|
98
|
-
|
99
|
-
@parts_failed = !parts_match(mail, @parts) if @parts
|
100
|
-
@body_failed = !body_match(mail, @body) if @body
|
101
|
-
@sender_failed = !regexp_or_string_match_in_array(mail.from, @sender) if @sender
|
102
|
-
@recipient_failed = !regexp_or_string_match_in_array(mail.to, @recipient) if @recipient
|
103
|
-
@cc_failed = !regexp_or_string_match_in_array(mail.cc, @cc) if @cc
|
104
|
-
@cc_recipients_failed = !match_array_in_array(mail.cc, @cc_recipients) if @cc_recipients
|
105
|
-
@bcc_failed = !regexp_or_string_match_in_array(mail.bcc, @bcc) if @bcc
|
106
|
-
@bcc_recipients_failed = !match_array_in_array(mail.bcc, @bcc_recipients) if @bcc_recipients
|
107
|
-
@multipart_failed = (mail.multipart? != @multipart) if defined?(@multipart)
|
108
|
-
return true unless anything_failed?
|
104
|
+
::ActionMailer::Base.deliveries.all? do |mail|
|
105
|
+
mail_matches?(mail)
|
109
106
|
end
|
110
|
-
|
111
|
-
false
|
112
107
|
end
|
113
108
|
|
114
109
|
def failure_message
|
@@ -123,10 +118,13 @@ module Shoulda # :nodoc:
|
|
123
118
|
description = "send an email"
|
124
119
|
description << " with a subject of #{@email_subject.inspect}" if @email_subject
|
125
120
|
description << " containing #{@body.inspect}" if @body
|
126
|
-
@parts
|
127
|
-
|
128
|
-
|
121
|
+
if @parts
|
122
|
+
@parts.each do |_, body, content_type|
|
123
|
+
description << " having a #{content_type} part containing #{body.inspect}"
|
124
|
+
end
|
125
|
+
end
|
129
126
|
description << " from #{@sender.inspect}" if @sender
|
127
|
+
description << " reply to #{@reply_to.inspect}" if @reply_to
|
130
128
|
description << " to #{@recipient.inspect}" if @recipient
|
131
129
|
description << " cc #{@cc.inspect}" if @cc
|
132
130
|
description << " with cc #{@cc_recipients.inspect}" if @cc_recipients
|
@@ -145,6 +143,7 @@ module Shoulda # :nodoc:
|
|
145
143
|
expectation << " with a #{content_type} part containing #{body}"
|
146
144
|
end if @parts && @parts_failed
|
147
145
|
expectation << " from #{@sender.inspect}" if @sender_failed
|
146
|
+
expectation << " reply to #{@reply_to.inspect}" if @reply_to_failed
|
148
147
|
expectation << " to #{@recipient.inspect}" if @recipient_failed
|
149
148
|
expectation << " cc #{@cc.inspect}" if @cc_failed
|
150
149
|
expectation << " with cc #{@cc_recipients.inspect}" if @cc_recipients_failed
|
@@ -160,15 +159,32 @@ module Shoulda # :nodoc:
|
|
160
159
|
end.join("\n")
|
161
160
|
end
|
162
161
|
|
162
|
+
def mail_matches?(mail)
|
163
|
+
@subject_failed = !regexp_or_string_match(mail.subject, @email_subject) if @email_subject
|
164
|
+
@parts_failed = !parts_match(mail, @parts) if @parts
|
165
|
+
@body_failed = !body_match(mail, @body) if @body
|
166
|
+
@sender_failed = !regexp_or_string_match_in_array(mail.from, @sender) if @sender
|
167
|
+
@reply_to_failed = !regexp_or_string_match_in_array(mail.reply_to, @reply_to) if @reply_to
|
168
|
+
@recipient_failed = !regexp_or_string_match_in_array(mail.to, @recipient) if @recipient
|
169
|
+
@cc_failed = !regexp_or_string_match_in_array(mail.cc, @cc) if @cc
|
170
|
+
@cc_recipients_failed = !match_array_in_array(mail.cc, @cc_recipients) if @cc_recipients
|
171
|
+
@bcc_failed = !regexp_or_string_match_in_array(mail.bcc, @bcc) if @bcc
|
172
|
+
@bcc_recipients_failed = !match_array_in_array(mail.bcc, @bcc_recipients) if @bcc_recipients
|
173
|
+
@multipart_failed = (mail.multipart? != @multipart) if defined?(@multipart)
|
174
|
+
|
175
|
+
! anything_failed?
|
176
|
+
end
|
177
|
+
|
163
178
|
def anything_failed?
|
164
|
-
@subject_failed || @body_failed || @sender_failed || @
|
165
|
-
@
|
166
|
-
@parts_failed || @multipart_failed
|
179
|
+
@subject_failed || @body_failed || @sender_failed || @reply_to_failed ||
|
180
|
+
@recipient_failed || @cc_failed || @cc_recipients_failed || @bcc_failed ||
|
181
|
+
@bcc_recipients_failed || @parts_failed || @multipart_failed
|
167
182
|
end
|
168
183
|
|
169
184
|
def normalize_blocks
|
170
185
|
@email_subject = @context.instance_eval(&@email_subject_block) if @email_subject_block
|
171
186
|
@sender = @context.instance_eval(&@sender_block) if @sender_block
|
187
|
+
@reply_to = @context.instance_eval(&@reply_to_block) if @reply_to_block
|
172
188
|
@body = @context.instance_eval(&@body_block) if @body_block
|
173
189
|
@recipient = @context.instance_eval(&@recipient_block) if @recipient_block
|
174
190
|
@cc = @context.instance_eval(&@cc_block) if @cc_block
|
@@ -205,7 +221,7 @@ module Shoulda # :nodoc:
|
|
205
221
|
target_array.sort!
|
206
222
|
match_array.sort!
|
207
223
|
|
208
|
-
target_array.each_cons(match_array.size).include?
|
224
|
+
target_array.each_cons(match_array.size).include?(match_array)
|
209
225
|
end
|
210
226
|
|
211
227
|
def body_match(mail, a_regexp_or_string)
|
@@ -8,6 +8,7 @@ require 'shoulda/matchers/active_model/validate_presence_of_matcher'
|
|
8
8
|
require 'shoulda/matchers/active_model/validate_format_of_matcher'
|
9
9
|
require 'shoulda/matchers/active_model/validate_uniqueness_of_matcher'
|
10
10
|
require 'shoulda/matchers/active_model/validate_acceptance_of_matcher'
|
11
|
+
require 'shoulda/matchers/active_model/validate_confirmation_of_matcher'
|
11
12
|
require 'shoulda/matchers/active_model/validate_numericality_of_matcher'
|
12
13
|
require 'shoulda/matchers/active_model/allow_mass_assignment_of_matcher'
|
13
14
|
|
@@ -9,20 +9,23 @@ module Shoulda # :nodoc:
|
|
9
9
|
#
|
10
10
|
# In Rails 3.1 you can check role as well:
|
11
11
|
#
|
12
|
-
# it { should
|
12
|
+
# it { should allow_mass_assignment_of(:first_name).as(:admin) }
|
13
13
|
#
|
14
14
|
def allow_mass_assignment_of(value)
|
15
15
|
AllowMassAssignmentOfMatcher.new(value)
|
16
16
|
end
|
17
17
|
|
18
18
|
class AllowMassAssignmentOfMatcher # :nodoc:
|
19
|
+
attr_reader :failure_message, :negative_failure_message
|
19
20
|
|
20
21
|
def initialize(attribute)
|
21
22
|
@attribute = attribute.to_s
|
22
23
|
end
|
23
24
|
|
24
25
|
def as(role)
|
25
|
-
|
26
|
+
unless at_least_rails_3_1?
|
27
|
+
raise "You can specify role only in Rails 3.1 or greater"
|
28
|
+
end
|
26
29
|
@role = role
|
27
30
|
self
|
28
31
|
end
|
@@ -45,18 +48,14 @@ module Shoulda # :nodoc:
|
|
45
48
|
true
|
46
49
|
else
|
47
50
|
if whitelisting?
|
48
|
-
@failure_message =
|
49
|
-
"Expected #{@attribute} to be accessible"
|
51
|
+
@failure_message = "Expected #{@attribute} to be accessible"
|
50
52
|
else
|
51
|
-
@failure_message =
|
52
|
-
"Did not expect #{@attribute} to be protected"
|
53
|
+
@failure_message = "Did not expect #{@attribute} to be protected"
|
53
54
|
end
|
54
55
|
false
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
58
|
-
attr_reader :failure_message, :negative_failure_message
|
59
|
-
|
60
59
|
def description
|
61
60
|
"allow mass assignment of #{@attribute}"
|
62
61
|
end
|
@@ -80,7 +79,7 @@ module Shoulda # :nodoc:
|
|
80
79
|
end
|
81
80
|
|
82
81
|
def authorizer
|
83
|
-
if
|
82
|
+
if at_least_rails_3_1?
|
84
83
|
@subject.class.active_authorizer[@role]
|
85
84
|
else
|
86
85
|
@subject.class.active_authorizer
|
@@ -91,7 +90,7 @@ module Shoulda # :nodoc:
|
|
91
90
|
@subject.class.name
|
92
91
|
end
|
93
92
|
|
94
|
-
def
|
93
|
+
def at_least_rails_3_1?
|
95
94
|
::ActiveModel::VERSION::MAJOR == 3 && ::ActiveModel::VERSION::MINOR >= 1
|
96
95
|
end
|
97
96
|
end
|
@@ -2,7 +2,10 @@ module Shoulda # :nodoc:
|
|
2
2
|
module Matchers
|
3
3
|
module ActiveModel # :nodoc:
|
4
4
|
|
5
|
-
# Ensures that the attribute can be set to the given value.
|
5
|
+
# Ensures that the attribute can be set to the given value or values. If
|
6
|
+
# multiple values are given the match succeeds only if all given values
|
7
|
+
# are allowed. Otherwise, the matcher fails at the first bad value in the
|
8
|
+
# argument list (the remaining arguments are not processed then).
|
6
9
|
#
|
7
10
|
# Options:
|
8
11
|
# * <tt>with_message</tt> - value the test expects to find in
|
@@ -13,15 +16,19 @@ module Shoulda # :nodoc:
|
|
13
16
|
# it { should_not allow_value('bad').for(:isbn) }
|
14
17
|
# it { should allow_value("isbn 1 2345 6789 0").for(:isbn) }
|
15
18
|
#
|
16
|
-
def allow_value(
|
17
|
-
|
19
|
+
def allow_value(*values)
|
20
|
+
if values.empty?
|
21
|
+
raise ArgumentError, "need at least one argument"
|
22
|
+
else
|
23
|
+
AllowValueMatcher.new(*values)
|
24
|
+
end
|
18
25
|
end
|
19
26
|
|
20
27
|
class AllowValueMatcher # :nodoc:
|
21
28
|
include Helpers
|
22
29
|
|
23
|
-
def initialize(
|
24
|
-
@
|
30
|
+
def initialize(*values)
|
31
|
+
@values_to_match = values
|
25
32
|
end
|
26
33
|
|
27
34
|
def for(attribute)
|
@@ -30,17 +37,17 @@ module Shoulda # :nodoc:
|
|
30
37
|
end
|
31
38
|
|
32
39
|
def with_message(message)
|
33
|
-
@expected_message = message
|
40
|
+
@expected_message = message
|
34
41
|
self
|
35
42
|
end
|
36
43
|
|
37
44
|
def matches?(instance)
|
38
45
|
@instance = instance
|
39
|
-
|
40
|
-
@
|
46
|
+
@values_to_match.none? do |value|
|
47
|
+
@value = value
|
48
|
+
@instance.send("#{@attribute}=", @value)
|
49
|
+
errors_match?
|
41
50
|
end
|
42
|
-
@instance.send("#{@attribute}=", @value)
|
43
|
-
!errors_match?
|
44
51
|
end
|
45
52
|
|
46
53
|
def failure_message
|
@@ -52,48 +59,47 @@ module Shoulda # :nodoc:
|
|
52
59
|
end
|
53
60
|
|
54
61
|
def description
|
55
|
-
"allow #{@attribute} to be set to #{
|
62
|
+
"allow #{@attribute} to be set to #{allowed_values}"
|
56
63
|
end
|
57
64
|
|
58
65
|
private
|
59
66
|
|
60
67
|
def errors_match?
|
61
|
-
@instance.valid?
|
62
|
-
|
63
|
-
|
64
|
-
|
68
|
+
if @instance.valid?
|
69
|
+
false
|
70
|
+
else
|
71
|
+
if expected_message
|
72
|
+
errors_match_regexp? || errors_match_string?
|
73
|
+
else
|
74
|
+
errors_for_attribute.compact.any?
|
75
|
+
end
|
76
|
+
end
|
65
77
|
end
|
66
78
|
|
67
|
-
def errors_for_attribute
|
68
|
-
if instance.errors.respond_to?(:[])
|
69
|
-
instance.errors[attribute]
|
79
|
+
def errors_for_attribute
|
80
|
+
if @instance.errors.respond_to?(:[])
|
81
|
+
errors = @instance.errors[@attribute]
|
70
82
|
else
|
71
|
-
instance.errors.on(attribute)
|
83
|
+
errors = @instance.errors.on(@attribute)
|
72
84
|
end
|
85
|
+
Array.wrap(errors)
|
73
86
|
end
|
74
87
|
|
75
88
|
def errors_match_regexp?
|
76
|
-
if Regexp ===
|
77
|
-
@matched_error =
|
78
|
-
!@matched_error.nil?
|
79
|
-
else
|
80
|
-
false
|
89
|
+
if Regexp === expected_message
|
90
|
+
@matched_error = errors_for_attribute.detect { |e| e =~ expected_message }
|
81
91
|
end
|
82
92
|
end
|
83
93
|
|
84
94
|
def errors_match_string?
|
85
|
-
if
|
86
|
-
@matched_error =
|
87
|
-
true
|
88
|
-
else
|
89
|
-
false
|
95
|
+
if errors_for_attribute.include?(expected_message)
|
96
|
+
@matched_error = expected_message
|
90
97
|
end
|
91
98
|
end
|
92
99
|
|
93
100
|
def expectation
|
94
|
-
"
|
95
|
-
|
96
|
-
"when #{@attribute} is set to #{@value.inspect}"
|
101
|
+
includes_expected_message = expected_message ? "to include #{expected_message.inspect}" : ''
|
102
|
+
["errors", includes_expected_message, "when #{@attribute} is set to #{@value.inspect}"].join(' ')
|
97
103
|
end
|
98
104
|
|
99
105
|
def error_description
|
@@ -103,8 +109,29 @@ module Shoulda # :nodoc:
|
|
103
109
|
"errors: #{pretty_error_messages(@instance)}"
|
104
110
|
end
|
105
111
|
end
|
106
|
-
end
|
107
112
|
|
113
|
+
def allowed_values
|
114
|
+
if @values_to_match.length > 1
|
115
|
+
"any of [#{@values_to_match.map(&:inspect).join(', ')}]"
|
116
|
+
else
|
117
|
+
@values_to_match.first.inspect
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def expected_message
|
122
|
+
if @expected_message
|
123
|
+
if Symbol === @expected_message
|
124
|
+
default_error_message(@expected_message, :model_name => model_name, :attribute => @attribute)
|
125
|
+
else
|
126
|
+
@expected_message
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def model_name
|
132
|
+
@instance.class.to_s.underscore
|
133
|
+
end
|
134
|
+
end
|
108
135
|
end
|
109
136
|
end
|
110
137
|
end
|
@@ -3,9 +3,9 @@ module Shoulda # :nodoc:
|
|
3
3
|
module ActiveModel # :nodoc:
|
4
4
|
module Helpers
|
5
5
|
def pretty_error_messages(obj) # :nodoc:
|
6
|
-
obj.errors.map do |
|
7
|
-
msg = "#{
|
8
|
-
msg << " (#{obj.send(
|
6
|
+
obj.errors.map do |attribute, model|
|
7
|
+
msg = "#{attribute} #{model}"
|
8
|
+
msg << " (#{obj.send(attribute).inspect})" unless attribute.to_sym == :base
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -16,12 +16,16 @@ module Shoulda # :nodoc:
|
|
16
16
|
# default_error_message(:blank)
|
17
17
|
# default_error_message(:too_short, :count => 5)
|
18
18
|
# default_error_message(:too_long, :count => 60)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
# default_error_message(:blank, :model_name => 'user', :attribute => 'name')
|
20
|
+
def default_error_message(key, options = {})
|
21
|
+
model_name = options.delete(:model_name)
|
22
|
+
attribute = options.delete(:attribute)
|
23
|
+
default_translation = [ :"activerecord.errors.models.#{model_name}.#{key}",
|
24
|
+
:"activerecord.errors.messages.#{key}",
|
25
|
+
:"errors.attributes.#{attribute}.#{key}",
|
26
|
+
:"errors.messages.#{key}" ]
|
27
|
+
I18n.translate(:"activerecord.errors.models.#{model_name}.attributes.#{attribute}.#{key}",
|
28
|
+
{ :default => default_translation }.merge(options))
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Shoulda # :nodoc:
|
2
|
+
module Matchers
|
3
|
+
module ActiveModel # :nodoc:
|
4
|
+
# Ensures that the model's attribute matches confirmation
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
# it { should validate_confirmation_of(:password) }
|
8
|
+
#
|
9
|
+
def validate_confirmation_of(attr)
|
10
|
+
ValidateConfirmationOfMatcher.new(attr)
|
11
|
+
end
|
12
|
+
|
13
|
+
class ValidateConfirmationOfMatcher < ValidationMatcher # :nodoc:
|
14
|
+
include Helpers
|
15
|
+
|
16
|
+
def initialize(attribute)
|
17
|
+
@attribute = attribute
|
18
|
+
@confirmation = "#{attribute}_confirmation"
|
19
|
+
end
|
20
|
+
|
21
|
+
def with_message(message)
|
22
|
+
@message = message if message
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def description
|
27
|
+
"require #{@base_attribute} to match #{@attribute}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def matches?(subject)
|
31
|
+
super(subject)
|
32
|
+
@message ||= :confirmation
|
33
|
+
|
34
|
+
disallows_different_value &&
|
35
|
+
allows_same_value &&
|
36
|
+
allows_missing_confirmation
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def disallows_different_value
|
42
|
+
set_confirmation("some value")
|
43
|
+
matches = disallows_value_of("different value", @message)
|
44
|
+
end
|
45
|
+
|
46
|
+
def allows_same_value
|
47
|
+
set_confirmation("same value")
|
48
|
+
allows_value_of("same value", @message)
|
49
|
+
end
|
50
|
+
|
51
|
+
def allows_missing_confirmation
|
52
|
+
set_confirmation(nil)
|
53
|
+
allows_value_of("any value", @message)
|
54
|
+
end
|
55
|
+
|
56
|
+
def set_confirmation(val)
|
57
|
+
setter = :"#{@confirmation}="
|
58
|
+
@subject.send(setter, val) if @subject.respond_to?(setter)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|