hydra-validations 0.3.2 → 0.4.0
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 +4 -4
- data/README.md +27 -9
- data/lib/hydra/validations.rb +1 -1
- data/lib/hydra/validations/cardinality.rb +45 -8
- data/lib/hydra/validations/enumerable_behavior.rb +8 -3
- data/lib/hydra/validations/uniqueness.rb +17 -14
- data/lib/hydra/validations/version.rb +1 -1
- data/spec/validations/cardinality_validator_spec.rb +199 -0
- data/spec/validations/format_validator_spec.rb +60 -0
- data/spec/validations/helper_methods_spec.rb +63 -0
- data/spec/{validators → validations}/inclusion_validator_spec.rb +0 -0
- data/spec/{validators → validations}/uniqueness_validator_spec.rb +21 -34
- metadata +12 -11
- data/lib/hydra/validations/single_cardinality.rb +0 -32
- data/spec/validators/format_validator_spec.rb +0 -61
- data/spec/validators/single_cardinality_validator_spec.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cd9dc181595609320187b6967b7419c584e5592
|
4
|
+
data.tar.gz: e87ae57ed9847709bccd5979eee498381707cc13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45b9a25dd9f59461d336b8877e14371f67ef764ed0b879960f375f97e60236a646c29cef36660703598a2fe3ac46f6f7a7a0ea2ee1be020ea6552e94c914bfa7
|
7
|
+
data.tar.gz: 0212d9e7f159ddbacf0a291b4a80a91f95659aa95474c7cff67e337e57132fb37d2f39e2be660c4cfaaa0f856d51d62884c715196ca6b061522645e8c154aa23
|
data/README.md
CHANGED
@@ -25,13 +25,15 @@ and
|
|
25
25
|
bundle install
|
26
26
|
```
|
27
27
|
|
28
|
+
## EnumerableBehavior Mixin
|
29
|
+
|
28
30
|
## Validators
|
29
31
|
|
30
32
|
See also the source code and spec tests.
|
31
33
|
|
32
34
|
### FormatValidator
|
33
35
|
|
34
|
-
Extends the ActiveModel
|
36
|
+
Extends the ActiveModel::Validations::FormatValidator, adding EnumerableBehavior.
|
35
37
|
|
36
38
|
See documentation for ActiveModel::Validations::FormatValidator for usage and options.
|
37
39
|
|
@@ -63,7 +65,7 @@ end
|
|
63
65
|
|
64
66
|
### InclusionValidator
|
65
67
|
|
66
|
-
Extends
|
68
|
+
Extends ActiveModel::Validations::InclusionValidator, adding EnumerableBehavior.
|
67
69
|
|
68
70
|
See documentation for ActiveModel::Validations::InclusionValidator for usage and options.
|
69
71
|
|
@@ -73,6 +75,8 @@ class InclusionValidatable
|
|
73
75
|
include Hydra::Validations
|
74
76
|
attr_accessor :field
|
75
77
|
validates :field, inclusion: { in: ["foo", "bar", "baz"] }
|
78
|
+
# or using helper method ...
|
79
|
+
# validates_inclusion_of :field, in: ["foo", "bar", "baz"]
|
76
80
|
end
|
77
81
|
|
78
82
|
> v = InclusionValidatable.new
|
@@ -103,7 +107,6 @@ class UniquenessValidatable < ActiveFedora::Base
|
|
103
107
|
has_metadata name: 'descMetadata', type: ActiveFedora::QualifiedDublinCoreDatastream
|
104
108
|
has_attributes :title, datastream: 'descMetadata', multiple: false
|
105
109
|
# Can use with multi-value attributes, but single cardinality is required.
|
106
|
-
# See SingleCardinalityValidator below.
|
107
110
|
has_attributes :source, datastream: 'descMetadata', multiple: true
|
108
111
|
validates :source, uniqueness: { solr_name: "source_ssim" }
|
109
112
|
# ... or using helper method
|
@@ -111,20 +114,35 @@ class UniquenessValidatable < ActiveFedora::Base
|
|
111
114
|
end
|
112
115
|
```
|
113
116
|
|
114
|
-
###
|
117
|
+
### CardinalityValidator
|
118
|
+
|
119
|
+
Validates the cardinality of the attribute value.
|
120
|
+
|
121
|
+
CardinalityValidator is a subclass of ActiveModel::Validations::LengthValidator which
|
122
|
+
"tokenizes" values with `Array.wrap(value)`. The "cardinality" of the value
|
123
|
+
is the length the array. Hence,
|
124
|
+
|
125
|
+
- `nil` and empty enumerables have cardinality 0
|
126
|
+
- scalar values (including empty string) have cardinality 1.
|
115
127
|
|
116
|
-
|
128
|
+
CardinalityValidator customizes the `:wrong_length`, `:too_short` and `:too_long` messages
|
129
|
+
of LengthValidator to use language appropriate to cardinality. You can also override these
|
130
|
+
options.
|
117
131
|
|
118
132
|
```ruby
|
119
|
-
class
|
133
|
+
class CardinalityValidatable
|
120
134
|
include ActiveModel::Validations # required if not already included in class
|
121
135
|
include Hydra::Validations
|
122
136
|
attr_accessor :field
|
123
|
-
validates :field,
|
137
|
+
validates :field, cardinality: { is: 1 }
|
138
|
+
# or with helper method ...
|
139
|
+
# validates_cardinality_of :field, is: 1
|
140
|
+
# or, for single cardinality (same as above) ...
|
141
|
+
# validates_single_cardinality_of :field
|
124
142
|
end
|
125
143
|
|
126
|
-
>
|
127
|
-
=> [#<Hydra::Validations::
|
144
|
+
> CardinalityValidatable.validators
|
145
|
+
=> [#<Hydra::Validations::CardinalityValidator:0x007fb91d1e9460 @attributes=[:field], @options={:is=>1}>]
|
128
146
|
> v = Validatable.new
|
129
147
|
=> #<Validatable:0x007fb91d1c9188>
|
130
148
|
> v.field = "foo"
|
data/lib/hydra/validations.rb
CHANGED
@@ -14,7 +14,7 @@ module Hydra
|
|
14
14
|
protected
|
15
15
|
# Overwrites ActiveModel::Validations::ClassMethods, adding :allow_empty
|
16
16
|
def _validates_default_keys
|
17
|
-
[:if, :unless, :on, :allow_blank, :allow_nil
|
17
|
+
[:if, :unless, :on, :allow_blank, :allow_nil, :strict, :allow_empty]
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -1,20 +1,57 @@
|
|
1
|
+
require 'active_support/core_ext/array/wrap'
|
2
|
+
|
1
3
|
module Hydra
|
2
4
|
module Validations
|
3
5
|
#
|
4
|
-
#
|
6
|
+
# CardinalityValidator - A cardinality validator for enumerable values based on
|
7
|
+
# ActiveModel's LengthValidator.
|
8
|
+
#
|
9
|
+
# validates :field, cardinality: { minimum: 1, maximum: 5 }
|
10
|
+
# validates :field, cardinality: { in: 1..5 }
|
11
|
+
# validates :field, cardinality: { within: 1..5 }
|
12
|
+
# validates :field, cardinality: { is: 1 }
|
5
13
|
#
|
6
|
-
|
14
|
+
# See ActiveModel::Validations::LengthValidator for options.
|
15
|
+
#
|
16
|
+
class CardinalityValidator < ActiveModel::Validations::LengthValidator
|
17
|
+
|
18
|
+
def initialize(options = {})
|
19
|
+
super(default_options.merge(options))
|
20
|
+
end
|
7
21
|
|
8
|
-
def
|
9
|
-
return
|
10
|
-
|
22
|
+
def validate_each(record, attribute, value)
|
23
|
+
return if options[:allow_empty] && value.respond_to?(:empty?) && value.empty?
|
24
|
+
super
|
11
25
|
end
|
12
26
|
|
13
|
-
|
14
|
-
|
15
|
-
|
27
|
+
protected
|
28
|
+
|
29
|
+
def default_options
|
30
|
+
{ wrong_length: "has the wrong cardinality (should have %{count} value(s))",
|
31
|
+
too_short: "has too few values (minimum cardinality is %{count})",
|
32
|
+
too_long: "has too many values (maximum cardinality is %{count})"
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Override
|
39
|
+
def tokenize(value)
|
40
|
+
Array.wrap(value)
|
16
41
|
end
|
17
42
|
|
18
43
|
end
|
44
|
+
|
45
|
+
module HelperMethods
|
46
|
+
def validates_cardinality_of *attr_names
|
47
|
+
validates_with CardinalityValidator, _merge_attributes(attr_names)
|
48
|
+
end
|
49
|
+
|
50
|
+
def validates_single_cardinality_of *attr_names
|
51
|
+
options = _merge_attributes(attr_names).merge(is: 1)
|
52
|
+
validates_with CardinalityValidator, options
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
19
56
|
end
|
20
57
|
end
|
@@ -7,10 +7,15 @@ module Hydra
|
|
7
7
|
# Behavior includes 'fixing' each error message to include the specific value
|
8
8
|
# which was invalid.
|
9
9
|
#
|
10
|
-
# `allow_empty` option can be used instead of `allow_blank` for greater
|
10
|
+
# The `allow_empty` option can be used instead of `allow_blank` for greater
|
11
11
|
# clarity and precision with enumerable values. If a validator includes
|
12
|
-
# this mixin,
|
13
|
-
# `allow_empty` is
|
12
|
+
# this mixin, an empty enumerable value will *always* be invalid unless
|
13
|
+
# `allow_empty` is true.
|
14
|
+
#
|
15
|
+
# Note that `allow_nil` and `allow_blank` options apply to the enumerable
|
16
|
+
# value, not to its members. Thus, for example, `allow_blank: true` will
|
17
|
+
# not bypass validation of the value `[""]` even though its member `""`
|
18
|
+
# is blank.
|
14
19
|
#
|
15
20
|
module EnumerableBehavior
|
16
21
|
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
require 'hydra/validations/cardinality'
|
1
|
+
require 'active_support/core_ext/array/wrap'
|
3
2
|
|
4
3
|
module Hydra
|
5
4
|
module Validations
|
@@ -25,22 +24,26 @@ module Hydra
|
|
25
24
|
#
|
26
25
|
class UniquenessValidator < ActiveModel::EachValidator
|
27
26
|
|
28
|
-
include Cardinality
|
29
|
-
|
30
27
|
def check_validity!
|
31
|
-
|
32
|
-
|
28
|
+
if attributes.length > 1
|
29
|
+
raise ArgumentError, "UniquenessValidator accepts only a single attribute: #{attributes}"
|
30
|
+
end
|
31
|
+
unless options[:solr_name].present?
|
32
|
+
raise ArgumentError, "UniquenessValidator requires the :solr_name option be present."
|
33
|
+
end
|
33
34
|
end
|
34
35
|
|
35
36
|
def validate_each(record, attribute, value)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
wrapped_value = Array.wrap(value)
|
38
|
+
if wrapped_value.length > 1
|
39
|
+
record.errors.add(attribute, "can't have more than one value")
|
40
|
+
elsif wrapped_value.empty?
|
41
|
+
record.errors.add(attribute, "can't be empty") unless options[:allow_empty]
|
42
|
+
else
|
43
|
+
conditions = {options[:solr_name] => wrapped_value.first}
|
44
|
+
conditions.merge!("-id" => record.id) if record.persisted?
|
45
|
+
record.errors.add attribute, "has already been taken" if record.class.exists?(conditions)
|
46
|
+
end
|
44
47
|
end
|
45
48
|
|
46
49
|
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hydra::Validations::CardinalityValidator do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
class Validatable
|
7
|
+
include ActiveModel::Validations
|
8
|
+
include Hydra::Validations
|
9
|
+
attr_accessor :field
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
Validatable.clear_validators!
|
15
|
+
Validatable.validates :field, options
|
16
|
+
allow(record).to receive(:field) { value }
|
17
|
+
end
|
18
|
+
|
19
|
+
after(:all) { Object.send(:remove_const, :Validatable) }
|
20
|
+
|
21
|
+
let(:record) { Validatable.new }
|
22
|
+
|
23
|
+
let(:opts) { { cardinality: cardinality } }
|
24
|
+
|
25
|
+
shared_examples "it has cardinality 0" do
|
26
|
+
let(:options) { opts }
|
27
|
+
describe "and :is == 0" do
|
28
|
+
let(:cardinality) { { is: 0 } }
|
29
|
+
it "should be valid" do
|
30
|
+
expect(record).to be_valid
|
31
|
+
end
|
32
|
+
end
|
33
|
+
describe "and :is > 0" do
|
34
|
+
let(:cardinality) { { is: 1 } }
|
35
|
+
it "should be invalid" do
|
36
|
+
expect(record).to be_invalid
|
37
|
+
end
|
38
|
+
end
|
39
|
+
describe "and :minimum == 0" do
|
40
|
+
let(:cardinality) { { minimum: 0 } }
|
41
|
+
it "should be valid" do
|
42
|
+
expect(record).to be_valid
|
43
|
+
end
|
44
|
+
end
|
45
|
+
describe "and :minimum > 0" do
|
46
|
+
let(:cardinality) { { minimum: 1 } }
|
47
|
+
it "should be invalid" do
|
48
|
+
expect(record).to be_invalid
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
shared_examples "it has cardinality 1" do
|
54
|
+
let(:options) { opts }
|
55
|
+
describe "and is == 0" do
|
56
|
+
let(:cardinality) { { is: 0 } }
|
57
|
+
it "should be invalid" do
|
58
|
+
expect(record).to be_invalid
|
59
|
+
end
|
60
|
+
end
|
61
|
+
describe "and :is == 1" do
|
62
|
+
let(:cardinality) { { is: 1 } }
|
63
|
+
it "should be valid" do
|
64
|
+
expect(record).to be_valid
|
65
|
+
end
|
66
|
+
end
|
67
|
+
describe "and :is > 1" do
|
68
|
+
let(:cardinality) { { is: 2 } }
|
69
|
+
it "should be invalid" do
|
70
|
+
expect(record).to be_invalid
|
71
|
+
end
|
72
|
+
end
|
73
|
+
describe "and :minimum == 0" do
|
74
|
+
let(:cardinality) { { minimum: 0 } }
|
75
|
+
it "should be valid" do
|
76
|
+
expect(record).to be_valid
|
77
|
+
end
|
78
|
+
end
|
79
|
+
describe "and :minimum == 1" do
|
80
|
+
let(:cardinality) { { minimum: 1 } }
|
81
|
+
it "should be valid" do
|
82
|
+
expect(record).to be_valid
|
83
|
+
end
|
84
|
+
end
|
85
|
+
describe "and :minimum > 1" do
|
86
|
+
let(:cardinality) { { minimum: 2 } }
|
87
|
+
it "should be invalid" do
|
88
|
+
expect(record).to be_invalid
|
89
|
+
end
|
90
|
+
end
|
91
|
+
describe "and :maximum == 0" do
|
92
|
+
let(:cardinality) { { maximum: 0 } }
|
93
|
+
it "should be invalid" do
|
94
|
+
expect(record).to be_invalid
|
95
|
+
end
|
96
|
+
end
|
97
|
+
describe "and :maximum == 1" do
|
98
|
+
let(:cardinality) { { maximum: 1 } }
|
99
|
+
it "should be valid" do
|
100
|
+
expect(record).to be_valid
|
101
|
+
end
|
102
|
+
end
|
103
|
+
describe "and :maximum > 1" do
|
104
|
+
let(:cardinality) { { maximum: 2 } }
|
105
|
+
it "should be valid" do
|
106
|
+
expect(record).to be_valid
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "when value is nil" do
|
112
|
+
let(:value) { nil }
|
113
|
+
it_behaves_like "it has cardinality 0"
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "when value is an empty string" do
|
117
|
+
let(:value) { "" }
|
118
|
+
it_behaves_like "it has cardinality 1"
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "when value is a non-empty string" do
|
122
|
+
let(:value) { "foo" }
|
123
|
+
it_behaves_like "it has cardinality 1"
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "when value is an empty enumerable" do
|
127
|
+
let(:value) { [] }
|
128
|
+
it_behaves_like "it has cardinality 0"
|
129
|
+
describe "and `allow_empty: true`" do
|
130
|
+
let(:options) { opts.merge(allow_empty: true) }
|
131
|
+
describe "and :is != 0" do
|
132
|
+
let(:cardinality) { { is: 1 } }
|
133
|
+
it "should be valid" do
|
134
|
+
expect(record).to be_valid
|
135
|
+
end
|
136
|
+
end
|
137
|
+
describe "and :minimum > 0" do
|
138
|
+
let(:cardinality) { { minimum: 1 } }
|
139
|
+
it "should be valid" do
|
140
|
+
expect(record).to be_valid
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "when value is a non-empty enumerable" do
|
147
|
+
let(:value) { ["foo", "bar"] }
|
148
|
+
let(:options) { opts }
|
149
|
+
describe "and :is != length" do
|
150
|
+
let(:cardinality) { { is: 1 } }
|
151
|
+
it "should be invalid" do
|
152
|
+
expect(record).to be_invalid
|
153
|
+
end
|
154
|
+
end
|
155
|
+
describe "and :is == length" do
|
156
|
+
let(:cardinality) { { is: 2 } }
|
157
|
+
it "should be valid" do
|
158
|
+
expect(record).to be_valid
|
159
|
+
end
|
160
|
+
end
|
161
|
+
describe "and :minimum < length" do
|
162
|
+
let(:cardinality) { { minimum: 1 } }
|
163
|
+
it "should be valid" do
|
164
|
+
expect(record).to be_valid
|
165
|
+
end
|
166
|
+
end
|
167
|
+
describe "and :minimum == length" do
|
168
|
+
let(:cardinality) { { minimum: 2 } }
|
169
|
+
it "should be valid" do
|
170
|
+
expect(record).to be_valid
|
171
|
+
end
|
172
|
+
end
|
173
|
+
describe "and :minimum > length" do
|
174
|
+
let(:cardinality) { { minimum: 3 } }
|
175
|
+
it "should be invalid" do
|
176
|
+
expect(record).to be_invalid
|
177
|
+
end
|
178
|
+
end
|
179
|
+
describe "and :maximum < length" do
|
180
|
+
let(:cardinality) { { maximum: 1 } }
|
181
|
+
it "should be invalid" do
|
182
|
+
expect(record).to be_invalid
|
183
|
+
end
|
184
|
+
end
|
185
|
+
describe "and :maximum == length" do
|
186
|
+
let(:cardinality) { { maximum: 2 } }
|
187
|
+
it "should be valid" do
|
188
|
+
expect(record).to be_valid
|
189
|
+
end
|
190
|
+
end
|
191
|
+
describe "and :maximum > length" do
|
192
|
+
let(:cardinality) { { maximum: 3 } }
|
193
|
+
it "should be valid" do
|
194
|
+
expect(record).to be_valid
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hydra::Validations::FormatValidator do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
class Validatable
|
7
|
+
include ActiveModel::Validations
|
8
|
+
include Hydra::Validations
|
9
|
+
attr_accessor :field
|
10
|
+
validates :field, format: { with: /\A[[:alpha:]]+\Z/ }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:all) { Object.send(:remove_const, :Validatable) }
|
15
|
+
|
16
|
+
before(:each) { allow(record).to receive(:field) { value } }
|
17
|
+
|
18
|
+
let(:record) { Validatable.new }
|
19
|
+
|
20
|
+
describe "when the value is a scalar" do
|
21
|
+
describe "which matches the format" do
|
22
|
+
let(:value) { "foo" }
|
23
|
+
it "should be valid" do
|
24
|
+
expect(record).to be_valid
|
25
|
+
end
|
26
|
+
end
|
27
|
+
describe "which does not match the format" do
|
28
|
+
let(:value) { "foo1" }
|
29
|
+
it "should be invalid" do
|
30
|
+
expect(record).to be_invalid
|
31
|
+
end
|
32
|
+
it "should have the standard error message" do
|
33
|
+
record.valid?
|
34
|
+
# TODO i18n
|
35
|
+
expect(record.errors[:field]).to eq ["is invalid"]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "when the value is an enumerable" do
|
41
|
+
describe "and all value members match the format" do
|
42
|
+
let(:value) { ["foo", "bar"] }
|
43
|
+
it "should be valid" do
|
44
|
+
expect(record).to be_valid
|
45
|
+
end
|
46
|
+
end
|
47
|
+
describe "and one value member does not match the format" do
|
48
|
+
let(:value) { ["foo1", "bar"] }
|
49
|
+
it "should be invalid" do
|
50
|
+
expect(record).to be_invalid
|
51
|
+
end
|
52
|
+
it "should 'fix' the error message to include the value" do
|
53
|
+
record.valid?
|
54
|
+
# TODO i18n
|
55
|
+
expect(record.errors[:field]).to eq ["value \"foo1\" is invalid"]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hydra::Validations::HelperMethods do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
class Validatable
|
7
|
+
include ActiveModel::Validations
|
8
|
+
include Hydra::Validations
|
9
|
+
attr_accessor :field
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
before(:each) { Validatable.clear_validators! }
|
14
|
+
|
15
|
+
after(:all) { Object.send(:remove_const, :Validatable) }
|
16
|
+
|
17
|
+
subject { Validatable.validators.first }
|
18
|
+
|
19
|
+
describe ".validates_cardinality_of" do
|
20
|
+
before { Validatable.validates_cardinality_of :field, is: 1 }
|
21
|
+
it "should add a cardinality validator" do
|
22
|
+
expect(subject).to be_a Hydra::Validations::CardinalityValidator
|
23
|
+
expect(subject.options).to include({ is: 1 })
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe ".validates_single_cardinality_of" do
|
28
|
+
before { Validatable.validates_single_cardinality_of :field }
|
29
|
+
it "should add a cardinality validator having :is=>1" do
|
30
|
+
expect(subject).to be_a Hydra::Validations::CardinalityValidator
|
31
|
+
expect(subject.attributes).to eq [:field]
|
32
|
+
expect(subject.options).to include({ is: 1 })
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe ".validates_format_of" do
|
37
|
+
before { Validatable.validates_format_of :field, with: /\A[[:alpha:]]+\Z/ }
|
38
|
+
it "should add a format validator" do
|
39
|
+
expect(subject).to be_a Hydra::Validations::FormatValidator
|
40
|
+
expect(subject.attributes).to eq [:field]
|
41
|
+
expect(subject.options).to include({ with: /\A[[:alpha:]]+\Z/ })
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe ".validates_inclusion_of" do
|
46
|
+
before { Validatable.validates_inclusion_of :field, in: ["foo", "bar", "baz"] }
|
47
|
+
it "should add an inclusion validator" do
|
48
|
+
expect(subject).to be_a Hydra::Validations::InclusionValidator
|
49
|
+
expect(subject.attributes).to eq [:field]
|
50
|
+
expect(subject.options).to include({ in: ["foo", "bar", "baz"] })
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe ".validates_uniqueness_of" do
|
55
|
+
before { Validatable.validates_uniqueness_of :title, solr_name: "title_ssi" }
|
56
|
+
it "should add a uniqueness validator" do
|
57
|
+
expect(subject).to be_a Hydra::Validations::UniquenessValidator
|
58
|
+
expect(subject.attributes).to eq [:title]
|
59
|
+
expect(subject.options).to include({ solr_name: "title_ssi" })
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
File without changes
|
@@ -1,21 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'support/shared_examples_for_validators'
|
3
3
|
|
4
|
-
shared_examples "it validates the uniqueness of the attribute value" do
|
5
|
-
context "when the value is not taken" do
|
6
|
-
before { allow(Validatable).to receive(:exists?).with(conditions) { false } }
|
7
|
-
it "should be valid" do
|
8
|
-
expect(subject).to be_valid
|
9
|
-
end
|
10
|
-
end
|
11
|
-
context "when the value is taken" do
|
12
|
-
before { allow(Validatable).to receive(:exists?).with(conditions) { true } }
|
13
|
-
it "should not be valid" do
|
14
|
-
expect(subject).not_to be_valid
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
4
|
describe Hydra::Validations::UniquenessValidator do
|
20
5
|
|
21
6
|
before(:all) do
|
@@ -41,8 +26,9 @@ describe Hydra::Validations::UniquenessValidator do
|
|
41
26
|
|
42
27
|
after(:all) { Object.send(:remove_const, :Validatable) }
|
43
28
|
|
29
|
+
before(:each) { Validatable.clear_validators! }
|
30
|
+
|
44
31
|
describe "exceptions" do
|
45
|
-
before { Validatable.clear_validators! }
|
46
32
|
it "cannot be used on more than one attribute at a time" do
|
47
33
|
expect { Validatable.validates :title, :source, uniqueness: { solr_name: "snafu_ssim" } }.to raise_error
|
48
34
|
end
|
@@ -52,18 +38,26 @@ describe Hydra::Validations::UniquenessValidator do
|
|
52
38
|
end
|
53
39
|
|
54
40
|
describe "validation" do
|
41
|
+
|
55
42
|
subject { Validatable.new(pid: "foobar:1", title: "I am Unique!", source: ["Outer Space"]) }
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
Validatable.
|
43
|
+
|
44
|
+
shared_examples "it validates the uniqueness of the attribute value" do
|
45
|
+
context "when the value is not taken" do
|
46
|
+
before { allow(Validatable).to receive(:exists?).with(conditions) { false } }
|
47
|
+
it "should be valid" do
|
48
|
+
expect(subject).to be_valid
|
49
|
+
end
|
60
50
|
end
|
61
|
-
context "
|
62
|
-
before { allow(Validatable).to receive(:exists?) {
|
63
|
-
|
64
|
-
|
51
|
+
context "when the value is taken" do
|
52
|
+
before { allow(Validatable).to receive(:exists?).with(conditions) { true } }
|
53
|
+
it "should not be valid" do
|
54
|
+
expect(subject).not_to be_valid
|
65
55
|
end
|
66
56
|
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "with a scalar attribute (:multiple=>false)" do
|
60
|
+
before { Validatable.validates :title, uniqueness: { solr_name: "title_ssi" } }
|
67
61
|
context "when the record is new" do
|
68
62
|
before { allow(subject).to receive(:persisted?) { false } }
|
69
63
|
it_behaves_like "it validates the uniqueness of the attribute value" do
|
@@ -77,17 +71,9 @@ describe Hydra::Validations::UniquenessValidator do
|
|
77
71
|
end
|
78
72
|
end
|
79
73
|
end
|
74
|
+
|
80
75
|
context "with an enumerable attribute (:multiple=>true)" do
|
81
|
-
before
|
82
|
-
Validatable.clear_validators!
|
83
|
-
Validatable.validates_uniqueness_of :source, solr_name: "source_ssim"
|
84
|
-
end
|
85
|
-
context "cardinality validation" do
|
86
|
-
before { allow(Validatable).to receive(:exists?) { false } }
|
87
|
-
it_behaves_like "it validates the single cardinality of an enumerable attribute" do
|
88
|
-
let(:attribute) { :source }
|
89
|
-
end
|
90
|
-
end
|
76
|
+
before { Validatable.validates :source, uniqueness: { solr_name: "source_ssim" } }
|
91
77
|
context "when the record is new" do
|
92
78
|
before { allow(subject).to receive(:persisted?) { false } }
|
93
79
|
it_behaves_like "it validates the uniqueness of the attribute value" do
|
@@ -101,5 +87,6 @@ describe Hydra::Validations::UniquenessValidator do
|
|
101
87
|
end
|
102
88
|
end
|
103
89
|
end
|
90
|
+
|
104
91
|
end
|
105
92
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hydra-validations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dchandekstark
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -88,15 +88,15 @@ files:
|
|
88
88
|
- lib/hydra/validations/enumerable_behavior.rb
|
89
89
|
- lib/hydra/validations/format.rb
|
90
90
|
- lib/hydra/validations/inclusion.rb
|
91
|
-
- lib/hydra/validations/single_cardinality.rb
|
92
91
|
- lib/hydra/validations/uniqueness.rb
|
93
92
|
- lib/hydra/validations/version.rb
|
94
93
|
- spec/spec_helper.rb
|
95
94
|
- spec/support/shared_examples_for_validators.rb
|
96
|
-
- spec/
|
97
|
-
- spec/
|
98
|
-
- spec/
|
99
|
-
- spec/
|
95
|
+
- spec/validations/cardinality_validator_spec.rb
|
96
|
+
- spec/validations/format_validator_spec.rb
|
97
|
+
- spec/validations/helper_methods_spec.rb
|
98
|
+
- spec/validations/inclusion_validator_spec.rb
|
99
|
+
- spec/validations/uniqueness_validator_spec.rb
|
100
100
|
homepage: https://github.com/duke-libraries/hydra-validations
|
101
101
|
licenses:
|
102
102
|
- APACHE2
|
@@ -125,7 +125,8 @@ summary: Validations for Hydra applications, based on ActiveModel::Validations
|
|
125
125
|
test_files:
|
126
126
|
- spec/spec_helper.rb
|
127
127
|
- spec/support/shared_examples_for_validators.rb
|
128
|
-
- spec/
|
129
|
-
- spec/
|
130
|
-
- spec/
|
131
|
-
- spec/
|
128
|
+
- spec/validations/cardinality_validator_spec.rb
|
129
|
+
- spec/validations/format_validator_spec.rb
|
130
|
+
- spec/validations/helper_methods_spec.rb
|
131
|
+
- spec/validations/inclusion_validator_spec.rb
|
132
|
+
- spec/validations/uniqueness_validator_spec.rb
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'hydra/validations/cardinality'
|
2
|
-
|
3
|
-
module Hydra
|
4
|
-
module Validations
|
5
|
-
#
|
6
|
-
# SingleCardinalityValidator - validates that an enumerator value has size 0 or 1
|
7
|
-
#
|
8
|
-
# validates :myattr, single_cardinality: true
|
9
|
-
# validates_single_cardinality_of :myattr
|
10
|
-
#
|
11
|
-
# Blank and nil values are considered valid (even without :allow_blank or :allow_nil
|
12
|
-
# validator options).
|
13
|
-
#
|
14
|
-
class SingleCardinalityValidator < ActiveModel::EachValidator
|
15
|
-
|
16
|
-
include Cardinality
|
17
|
-
|
18
|
-
def validate_each(record, attribute, value)
|
19
|
-
validate_cardinality(:single, record, attribute, value)
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
module HelperMethods
|
25
|
-
def validates_single_cardinality_of *attr_names
|
26
|
-
validates_with SingleCardinalityValidator, _merge_attributes(attr_names)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
@@ -1,61 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'support/shared_examples_for_validators'
|
3
|
-
|
4
|
-
shared_examples "it validates the format of each member of the attribute value" do
|
5
|
-
context "all attribute value members are valid" do
|
6
|
-
before { record.field = ["foo", "bar"] }
|
7
|
-
it "should be valid" do
|
8
|
-
expect(record).to be_valid
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
context "one of the attribute value members is invalid" do
|
13
|
-
before { record.field = ["foo1", "bar"] }
|
14
|
-
it "should be invalid" do
|
15
|
-
expect(record).to be_invalid
|
16
|
-
end
|
17
|
-
it "should 'fix' the error message to include the value" do
|
18
|
-
record.valid?
|
19
|
-
expect(record.errors[:field]).to eq ["value \"foo1\" is invalid"]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe Hydra::Validations::FormatValidator do
|
25
|
-
|
26
|
-
before(:all) do
|
27
|
-
class Validatable
|
28
|
-
include ActiveModel::Validations
|
29
|
-
include Hydra::Validations
|
30
|
-
attr_accessor :field
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
before(:each) { Validatable.clear_validators! }
|
35
|
-
|
36
|
-
after(:all) { Object.send(:remove_const, :Validatable) }
|
37
|
-
|
38
|
-
describe "class methods" do
|
39
|
-
describe ".validates" do
|
40
|
-
before { Validatable.validates :field, format: { with: /\A[[:alpha:]]+\Z/ } }
|
41
|
-
it_behaves_like "it validates the format of each member of the attribute value" do
|
42
|
-
let(:record) { Validatable.new }
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
describe "helper methods" do
|
47
|
-
describe ".validates_format_of" do
|
48
|
-
before { Validatable.validates_format_of :field, with: /\A[[:alpha:]]+\Z/ }
|
49
|
-
it_behaves_like "it validates the format of each member of the attribute value" do
|
50
|
-
let(:record) { Validatable.new }
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
it_behaves_like "an enumerable validator" do
|
56
|
-
let(:options) { { format: { with: /\A[[:alpha:]]+\Z/ } } }
|
57
|
-
let(:record_class) { Validatable }
|
58
|
-
let(:attribute) { :field }
|
59
|
-
end
|
60
|
-
|
61
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'support/shared_examples_for_validators'
|
3
|
-
|
4
|
-
shared_examples "it validates the single cardinality of the attribute" do
|
5
|
-
it_behaves_like "it validates the single cardinality of a scalar attribute"
|
6
|
-
it_behaves_like "it validates the single cardinality of an enumerable attribute"
|
7
|
-
end
|
8
|
-
|
9
|
-
describe Hydra::Validations::SingleCardinalityValidator do
|
10
|
-
before(:all) do
|
11
|
-
class Validatable
|
12
|
-
include ActiveModel::Validations
|
13
|
-
include Hydra::Validations
|
14
|
-
attr_accessor :field
|
15
|
-
end
|
16
|
-
end
|
17
|
-
before(:each) { Validatable.clear_validators! }
|
18
|
-
after(:all) { Object.send(:remove_const, :Validatable) }
|
19
|
-
subject { Validatable.new }
|
20
|
-
describe ".validates" do
|
21
|
-
before { Validatable.validates :field, single_cardinality: true }
|
22
|
-
it_behaves_like "it validates the single cardinality of the attribute" do
|
23
|
-
let(:attribute) { :field }
|
24
|
-
end
|
25
|
-
end
|
26
|
-
describe ".validates_single_cardinality_of" do
|
27
|
-
before { Validatable.validates_single_cardinality_of :field }
|
28
|
-
it_behaves_like "it validates the single cardinality of the attribute" do
|
29
|
-
let(:attribute) { :field }
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|