/
validate_confirmation_of_matcher.rb
77 lines (64 loc) · 2.03 KB
/
validate_confirmation_of_matcher.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
module Shoulda # :nodoc:
module Matchers
module ActiveModel # :nodoc:
# Ensures that the model's attribute matches confirmation
#
# Example:
# it { should validate_confirmation_of(:password) }
#
def validate_confirmation_of(attr)
ValidateConfirmationOfMatcher.new(attr)
end
class ValidateConfirmationOfMatcher < ValidationMatcher # :nodoc:
include Helpers
attr_reader :attribute, :confirmation_attribute
def initialize(attribute)
@attribute = attribute
@confirmation_attribute = "#{attribute}_confirmation"
end
def with_message(message)
@message = message if message
self
end
def description
"require #{@confirmation_attribute} to match #{@attribute}"
end
def matches?(subject)
super(subject)
@message ||= :confirmation
disallows_different_value &&
allows_same_value &&
allows_missing_confirmation
end
private
def disallows_different_value
set_confirmation('some value')
disallows_value_of('different value') do |matcher|
matcher.with_message(@message, against: error_attribute)
end
end
def allows_same_value
set_confirmation('same value')
allows_value_of('same value') do |matcher|
matcher.with_message(@message, against: error_attribute)
end
end
def allows_missing_confirmation
set_confirmation(nil)
allows_value_of('any value') do |matcher|
matcher.with_message(@message, against: error_attribute)
end
end
def set_confirmation(val)
setter = :"#{@confirmation_attribute}="
if @subject.respond_to?(setter)
@subject.send(setter, val)
end
end
def error_attribute
RailsShim.validates_confirmation_of_error_attribute(self)
end
end
end
end
end