nested_validator 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
!binary "U0hBMQ==":
|
|
3
3
|
metadata.gz: !binary |-
|
|
4
|
-
|
|
4
|
+
NjkwYmI4M2ZlNjJmY2MwNmM5NzcyYmMxOTE4OGIyMDFhYjk2YWI2MA==
|
|
5
5
|
data.tar.gz: !binary |-
|
|
6
|
-
|
|
6
|
+
ODkyMzQ1YTYwZWI0MTA2ODdiY2RlNjI2Y2IwM2JkMjE1ODYxODRhOQ==
|
|
7
7
|
SHA512:
|
|
8
8
|
metadata.gz: !binary |-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
M2UzMDY5YTNiNzZkNDcwMTk0YmFjZWExZGM5ZWYyMmNhM2E5NDJiMDkzOTJj
|
|
10
|
+
Nzk4Zjk4ODM5OTQ0YTI0ZmM2OTVmODE5NjFhZmI3MDg2OWYyM2NkMDExNWQ3
|
|
11
|
+
NjA4NGNiN2EzMWM3YTQyM2IwMzU1ZDVjYzEwYjA3ODhlZmRhNTk=
|
|
12
12
|
data.tar.gz: !binary |-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
MzhhNTE1NGI2YThlZGY5ZjU0NjE3MTMzMDY3YWMzNWYzZTFiM2M0MGY4ZmZm
|
|
14
|
+
ZGMyNTE3ZDI1ZjI3MjM4YWEyZWU5ZWVlNjllNDRiNGRlYjVhYTJjNGIyNTNi
|
|
15
|
+
NjUwZWFiNmI2OGQxZmQwZDM4ZTBiMzI0YjcwZjQ4ODY3MmM4MDY=
|
data/Gemfile.lock
CHANGED
|
@@ -3,7 +3,9 @@ require 'active_support/core_ext/array'
|
|
|
3
3
|
|
|
4
4
|
module ActiveModel
|
|
5
5
|
module Validations
|
|
6
|
-
|
|
6
|
+
# Bases an object's validity on nested attributes.
|
|
7
|
+
#
|
|
8
|
+
# @see ActiveModel::Validations::HelperMethods#validates_nested validates_nested
|
|
7
9
|
class NestedValidator < EachValidator
|
|
8
10
|
|
|
9
11
|
private
|
|
@@ -64,7 +66,7 @@ module ActiveModel
|
|
|
64
66
|
end
|
|
65
67
|
|
|
66
68
|
module HelperMethods
|
|
67
|
-
# Bases an object's validity on nested
|
|
69
|
+
# Bases an object's validity on nested attributes.
|
|
68
70
|
#
|
|
69
71
|
# class Parent < ActiveRecord::Base
|
|
70
72
|
# has_one :child
|
|
@@ -110,6 +112,8 @@ module ActiveModel
|
|
|
110
112
|
# @option attr_names [boolean] :strict Specifies whether validation should be strict.
|
|
111
113
|
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
|
|
112
114
|
#
|
|
115
|
+
# @see ActiveModel::Validations::NestedValidator
|
|
116
|
+
|
|
113
117
|
def validates_nested(*attr_names)
|
|
114
118
|
validates_with NestedValidator, _merge_attributes(attr_names)
|
|
115
119
|
end
|
|
@@ -11,127 +11,129 @@
|
|
|
11
11
|
# it { should validate_nested(:child).only(:attribute1, :attribute2) }
|
|
12
12
|
# it { should validate_nested(:child).except(:attribute1) }
|
|
13
13
|
# end
|
|
14
|
+
if defined? RSpec
|
|
14
15
|
|
|
15
|
-
RSpec::Matchers.define :validate_nested do |child_name|
|
|
16
|
+
RSpec::Matchers.define :validate_nested do |child_name|
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
attr_accessor :child_name, :prefix, :only_keys, :except_keys # inputs
|
|
19
|
+
attr_accessor :parent, :actual_keys
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
TEST_KEY ||= :__test_key__
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
match do |parent|
|
|
24
|
+
self.prefix ||= ''
|
|
25
|
+
self.only_keys ||= []
|
|
26
|
+
self.except_keys ||= []
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
self.child_name = child_name
|
|
29
|
+
self.parent = parent
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
return false unless parent.respond_to? child_name
|
|
32
|
+
self.actual_keys = (error_keys_when_child_validity_is(false) - error_keys_when_child_validity_is(true))
|
|
33
|
+
return false if invalid_child_keys.present?
|
|
33
34
|
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
actual_keys == expected_keys
|
|
37
|
+
end
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
chain(:with_prefix) { |prefix| self.prefix = prefix }
|
|
40
|
+
chain(:only) { |*only| self.only_keys = only }
|
|
41
|
+
chain(:except) { |*except| self.except_keys = except }
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
def child
|
|
44
|
+
parent.send child_name
|
|
45
|
+
end
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
def error_keys_when_child_validity_is(valid)
|
|
48
|
+
child_error_keys = combine TEST_KEY, only_keys, except_keys
|
|
49
|
+
child_errors = child_error_keys.inject({}){|result, key| result[key] = ['error message'];result }
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
allow(child).to receive(:valid?) { valid }
|
|
52
|
+
allow(child).to receive(:errors) { valid ? [] : child_errors }
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
parent.valid?
|
|
55
|
+
parent.errors.keys
|
|
56
|
+
end
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
def expected_keys
|
|
59
|
+
expected_child_keys.map{|key| :"#{expected_prefix} #{key}"}
|
|
60
|
+
end
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
def expected_prefix
|
|
63
|
+
prefix.present? ? prefix : child_name
|
|
64
|
+
end
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
def actual_prefix
|
|
67
|
+
:"#{actual_keys.first.to_s.split.first}"
|
|
68
|
+
end
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
def expected_child_keys
|
|
71
|
+
expected_keys = only_keys.present? ? only_keys : [TEST_KEY]
|
|
72
|
+
unique_except_keys = except_keys - only_keys
|
|
73
|
+
combine expected_keys - unique_except_keys
|
|
74
|
+
end
|
|
74
75
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
def actual_child_keys
|
|
77
|
+
actual_keys.map{|key| key.to_s.sub(/^.*\s+/, '').to_sym }
|
|
78
|
+
end
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
def invalid_child_keys
|
|
81
|
+
(only_keys + except_keys).reject{|key| child.respond_to? key}
|
|
82
|
+
end
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
84
|
+
description do
|
|
85
|
+
message = "validate nested #{show child_name}"
|
|
86
|
+
message << " with only: #{show only_keys}" if only_keys.present?
|
|
87
|
+
message << " except: #{show except_keys}" if except_keys.present?
|
|
88
|
+
message << " with prefix #{show prefix}" if prefix.present?
|
|
89
|
+
message
|
|
90
|
+
end
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
92
|
+
failure_message do
|
|
93
|
+
case
|
|
94
|
+
when common_failure_message
|
|
95
|
+
common_failure_message
|
|
96
|
+
when (missing_child_keys = expected_child_keys - actual_child_keys - invalid_child_keys - [TEST_KEY]).present?
|
|
97
|
+
"#{parent} doesn't nest validations for: #{show missing_child_keys}"
|
|
98
|
+
when actual_keys.empty?
|
|
99
|
+
"parent doesn't nest validations for #{show child_name}"
|
|
100
|
+
when actual_prefix != expected_prefix
|
|
101
|
+
if prefix.present?
|
|
102
|
+
"parent uses a prefix of #{show actual_prefix} rather than #{show expected_prefix}"
|
|
103
|
+
else
|
|
104
|
+
"parent has a prefix of #{show actual_prefix}. Are you missing '.with_prefix(#{show actual_prefix})'?"
|
|
105
|
+
end
|
|
102
106
|
else
|
|
103
|
-
"parent
|
|
104
|
-
|
|
105
|
-
else
|
|
106
|
-
"parent does nest validations for: #{show except_keys & actual_child_keys}"
|
|
107
|
+
"parent does nest validations for: #{show except_keys & actual_child_keys}"
|
|
108
|
+
end
|
|
107
109
|
end
|
|
108
|
-
end
|
|
109
110
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
111
|
+
failure_message_when_negated do
|
|
112
|
+
case
|
|
113
|
+
when common_failure_message
|
|
114
|
+
common_failure_message
|
|
115
|
+
when (extras = only_keys & actual_child_keys).present?
|
|
116
|
+
"#{parent} does nest #{show child_name} validations for: #{show extras}"
|
|
117
|
+
when except_keys.present?
|
|
118
|
+
"#{parent} doesn't nest #{show child_name} validations for: #{show except_keys - actual_child_keys}"
|
|
119
|
+
when prefix.present?
|
|
120
|
+
"#{parent} does nest validations for: #{show child_name} with a prefix of #{show prefix}"
|
|
121
|
+
else
|
|
122
|
+
"#{parent} does nest validations for: #{show child_name}"
|
|
123
|
+
end
|
|
122
124
|
end
|
|
123
|
-
end
|
|
124
125
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
def common_failure_message
|
|
127
|
+
return "#{parent} doesn't respond to #{show child_name}" unless parent.respond_to?(child_name)
|
|
128
|
+
"#{child_name} doesn't respond to #{show invalid_child_keys}" if invalid_child_keys.present?
|
|
129
|
+
end
|
|
129
130
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
def show(value)
|
|
132
|
+
Array.wrap(value).map{|key| key.is_a?(Symbol) ? ":#{key}" : key.to_s}.join(', ')
|
|
133
|
+
end
|
|
133
134
|
|
|
134
|
-
|
|
135
|
-
|
|
135
|
+
def combine(*keys)
|
|
136
|
+
keys.flatten.compact
|
|
137
|
+
end
|
|
136
138
|
end
|
|
137
139
|
end
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
module NestedValidator
|
|
2
|
-
VERSION = '1.0.
|
|
3
|
-
end
|
|
2
|
+
VERSION = '1.0.2'
|
|
3
|
+
end
|
|
@@ -86,7 +86,7 @@ describe NestedValidator do
|
|
|
86
86
|
its('errors.messages') { should eq :'child1 attribute1' => ["can't be blank"] }
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
-
describe 'with "prefix: "OMG"'
|
|
89
|
+
describe 'with "prefix: "OMG"' do
|
|
90
90
|
subject { with_nested_options prefix: 'OMG' }
|
|
91
91
|
|
|
92
92
|
its('errors.messages') { puts subject.errors.messages; should eq :'OMG attribute1' => ["can't be blank"] }
|