hydra-validations 0.4.0 → 0.5.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/CONTRIBUTORS.md +1 -0
- data/README.md +164 -53
- data/lib/hydra/validations/presence.rb +16 -0
- data/lib/hydra/validations/version.rb +1 -1
- data/spec/validations/presence_validator_spec.rb +40 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e3b8f594ffb78eea70a27d91d92ed195988ae54
|
4
|
+
data.tar.gz: 1d2abb83db312b502a3570bd428a90e13d355750
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77946326c106d26eef65cc9e41380a5a2eb01bab261f637dafb6400e84b710b31b2d3f04b22b7c8ba426a62043270708ebe78156bb467b904cf64b3175accdbd
|
7
|
+
data.tar.gz: 6084c27aaf6326df5adc5216b3466ecce67d67d0558cab7a0993c8fce488f8c263fe4ee5011cfd66d152b121c13593c95e803fc218e84fe844fab8784941608d
|
data/CONTRIBUTORS.md
CHANGED
data/README.md
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
hydra-validations
|
2
2
|
=======================
|
3
3
|
|
4
|
-
Custom validators for Hydra applications, based on ActiveModel::Validations.
|
5
|
-
|
6
4
|
[](https://travis-ci.org/projecthydra-labs/hydra-validations)
|
7
5
|
[](http://badge.fury.io/rb/hydra-validations)
|
8
6
|
|
7
|
+
Custom validators based on ActiveModel::Validations, developed for Hydra applications.
|
8
|
+
|
9
9
|
## Dependencies
|
10
10
|
|
11
11
|
* Ruby >= 1.9.3
|
12
12
|
* ActiveModel 4.x
|
13
13
|
|
14
|
+
ActiveFedora 7.x is a run-time dependency of the UniquenessValidator only, and is not provided by this gem.
|
15
|
+
|
14
16
|
## Installation
|
15
17
|
|
16
18
|
Include in your Gemfile:
|
@@ -25,17 +27,109 @@ and
|
|
25
27
|
bundle install
|
26
28
|
```
|
27
29
|
|
30
|
+
## Why?
|
31
|
+
|
32
|
+
- Metadata values are (often) arrays (XML or RDF).
|
33
|
+
- ActiveModel validators don't distinguish between array values and scalar values.
|
34
|
+
- We want validators that validate each member of an array value.
|
35
|
+
|
36
|
+
### Example: PORO with ActiveModel::Validations
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
class Validatable
|
40
|
+
include ActiveModel::Validations
|
41
|
+
attr_accessor :type
|
42
|
+
validates_inclusion_of :type, in: %w(text image audio video)
|
43
|
+
end
|
44
|
+
|
45
|
+
>> record = Validatable.new
|
46
|
+
>> record.type = "text"
|
47
|
+
>> record.valid?
|
48
|
+
=> true
|
49
|
+
|
50
|
+
>> record.type = ["text", "image"]
|
51
|
+
>> record.valid?
|
52
|
+
=> false # not what we want :(
|
53
|
+
|
54
|
+
# now let's add Hydra::Validations ...
|
55
|
+
|
56
|
+
class CorrectlyValidatable
|
57
|
+
include ActiveModel::Validations
|
58
|
+
include Hydra::Validations
|
59
|
+
attr_accessor :type
|
60
|
+
validates_inclusion_of :type, in: %w(text image audio video)
|
61
|
+
end
|
62
|
+
|
63
|
+
>> record = CorrectlyValidatable.new
|
64
|
+
>> record.type = ["text", "image"]
|
65
|
+
>> record.valid?
|
66
|
+
=> true # Yay!
|
67
|
+
|
68
|
+
>> record.type = ["text", "newspaper"]
|
69
|
+
>> record.valid?
|
70
|
+
=> false
|
71
|
+
|
72
|
+
# tailors error message to specific invalid array value
|
73
|
+
>> puts record.errors.full_messages
|
74
|
+
Type value "newspaper" is not included in the list
|
75
|
+
```
|
76
|
+
|
77
|
+
### Example: ActiveTriples::Resource
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
class MyResource < ActiveTriples::Resource
|
81
|
+
# ActiveTriples::Resource includes ActiveModel::Validations
|
82
|
+
property :type, predicate: RDF::DC.type
|
83
|
+
validates_inclusion_of :type, in: %w(text image audio video)
|
84
|
+
end
|
85
|
+
|
86
|
+
>> resource = MyResource.new
|
87
|
+
>> resource.type = "text"
|
88
|
+
>> resource.valid?
|
89
|
+
=> false # Huh? Oh yeah, resource.type is actually an array ...
|
90
|
+
>> resource.type
|
91
|
+
=> ["text"]
|
92
|
+
|
93
|
+
class YourResource < ActiveTriples::Resource
|
94
|
+
include Hydra::Validations
|
95
|
+
property :type, predicate: RDF::DC.type
|
96
|
+
validates_inclusion_of :type, in: %w(text image audio video)
|
97
|
+
end
|
98
|
+
|
99
|
+
>> resource = YourResource.new
|
100
|
+
>> resource.type = "text"
|
101
|
+
=> "text"
|
102
|
+
>> resource.valid?
|
103
|
+
=> true # Yay!
|
104
|
+
|
105
|
+
>> resource.type << "newspapers"
|
106
|
+
>> resource.type
|
107
|
+
=> ["text", "newspapers"]
|
108
|
+
>> resource.valid?
|
109
|
+
=> false
|
110
|
+
>> puts resource.errors.full_messages
|
111
|
+
Type value "newspapers" is not included in the list
|
112
|
+
```
|
113
|
+
|
28
114
|
## EnumerableBehavior Mixin
|
29
115
|
|
116
|
+
`Hydra::Validations::EnumerableBehavior` is a mixin for an `ActiveModel::EachValidator` that validates each member of an enumerable value. See the [FormatValidator](#formatvalidator) and [InclusionValidator](#inclusionvalidator) below for examples.
|
117
|
+
|
118
|
+
EnumerableBehavior overrides `validate_each(record, attribute, value)` calling `super(record, attribute, member)` for each member of an enumerable value (i.e., responds to `:each`). The module "fixes" any error messages to include the specific member that failed validation -- for example, `"is invalid"` becomes `"value \"foo1\" is invalid"`, so the full message `"Identifier is invalid"` becomes `"Identifer value \"foo1\" is invalid"`.
|
119
|
+
|
120
|
+
**allow_nil, allow_blank, and allow_empty**
|
121
|
+
|
122
|
+
With EnumerableBehavior, validation of non-enumerables is unchanged (`validate_each` simply returns `super`); however, the validator options `allow_nil` and `allow_blank` *apply only to the original value* (the enumerable) and not to its members. For example, the value `[""]` with the option `allow_blank: true` will *not* bypass validation. As a result, empty enumerables will fail validation unless `allow_blank` is true or the special enumerable option `allow_empty` is true (that option does not bypass validation for non-enumerables that respond to `:empty?`, e.g., empty strings).
|
123
|
+
|
30
124
|
## Validators
|
31
125
|
|
32
126
|
See also the source code and spec tests.
|
33
127
|
|
34
128
|
### FormatValidator
|
35
129
|
|
36
|
-
Extends
|
130
|
+
Extends `ActiveModel::Validations::FormatValidator`, adding EnumerableBehavior.
|
37
131
|
|
38
|
-
See
|
132
|
+
See `ActiveModel::Validations::FormatValidator` for usage and options.
|
39
133
|
|
40
134
|
```ruby
|
41
135
|
class FormatValidatable
|
@@ -47,27 +141,34 @@ class FormatValidatable
|
|
47
141
|
# validates_format_of :field, with: /\A[[:alpha:]]+\Z/
|
48
142
|
end
|
49
143
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
144
|
+
>> record = FormatValidatable.new
|
145
|
+
=> #<FormatValidatable:0x007fe3cc0ece70>
|
146
|
+
>> record.field = "foo"
|
147
|
+
=> "foo"
|
148
|
+
>> record.valid?
|
149
|
+
=> true
|
150
|
+
>> record.field = ["foo"]
|
151
|
+
=> ["foo"]
|
152
|
+
>> record.valid?
|
153
|
+
=> true
|
154
|
+
>> record.field = ["foo", "bar"]
|
155
|
+
=> ["foo", "bar"]
|
156
|
+
>> record.valid?
|
157
|
+
=> true
|
158
|
+
>> record.field = ["foo1", "bar2"]
|
159
|
+
=> ["foo1", "bar2"]
|
160
|
+
>> record.valid?
|
161
|
+
=> false
|
162
|
+
>> puts record.errors.full_messages
|
163
|
+
Field value "foo1" is invalid
|
164
|
+
Field value "bar2" is invalid
|
64
165
|
```
|
65
166
|
|
66
167
|
### InclusionValidator
|
67
168
|
|
68
|
-
Extends ActiveModel::Validations::InclusionValidator
|
169
|
+
Extends `ActiveModel::Validations::InclusionValidator`, adding EnumerableBehavior.
|
69
170
|
|
70
|
-
See
|
171
|
+
See `ActiveModel::Validations::InclusionValidator` for usage and options.
|
71
172
|
|
72
173
|
```ruby
|
73
174
|
class InclusionValidatable
|
@@ -79,20 +180,30 @@ class InclusionValidatable
|
|
79
180
|
# validates_inclusion_of :field, in: ["foo", "bar", "baz"]
|
80
181
|
end
|
81
182
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
183
|
+
>> record = InclusionValidatable.new
|
184
|
+
=> #<InclusionValidatable:0x007fe3cbc40098>
|
185
|
+
>> record.field = "foo"
|
186
|
+
=> "foo"
|
187
|
+
>> record.valid?
|
188
|
+
=> true
|
189
|
+
>> record.field = "foo1"
|
190
|
+
=> "foo1"
|
191
|
+
>> record.valid?
|
192
|
+
=> false
|
193
|
+
>> record.field = ["foo"]
|
194
|
+
=> ["foo"]
|
195
|
+
>> record.valid?
|
196
|
+
=> true
|
197
|
+
>> record.field = ["foo", "bar"]
|
198
|
+
=> ["foo", "bar"]
|
199
|
+
>> record.valid?
|
200
|
+
=> true
|
201
|
+
>> record.field = ["foo", "bar1", "baz"]
|
202
|
+
=> ["foo", "bar1", "baz"]
|
203
|
+
>> record.valid?
|
204
|
+
=> false
|
205
|
+
>> puts record.errors.full_messages
|
206
|
+
Field value "bar1" is not included in the list
|
96
207
|
```
|
97
208
|
|
98
209
|
### UniquenessValidator
|
@@ -103,7 +214,7 @@ Intended for ActiveFedora 7.x.
|
|
103
214
|
|
104
215
|
```ruby
|
105
216
|
class UniquenessValidatable < ActiveFedora::Base
|
106
|
-
include Hydra::Validations
|
217
|
+
include Hydra::Validations # ActiveFedora::Base includes ActiveModel::Validations
|
107
218
|
has_metadata name: 'descMetadata', type: ActiveFedora::QualifiedDublinCoreDatastream
|
108
219
|
has_attributes :title, datastream: 'descMetadata', multiple: false
|
109
220
|
# Can use with multi-value attributes, but single cardinality is required.
|
@@ -118,9 +229,9 @@ end
|
|
118
229
|
|
119
230
|
Validates the cardinality of the attribute value.
|
120
231
|
|
121
|
-
CardinalityValidator
|
232
|
+
CardinalityValidator extends `ActiveModel::Validations::LengthValidator` and
|
122
233
|
"tokenizes" values with `Array.wrap(value)`. The "cardinality" of the value
|
123
|
-
is the length the array.
|
234
|
+
is therefore the length the array. Accordingly,
|
124
235
|
|
125
236
|
- `nil` and empty enumerables have cardinality 0
|
126
237
|
- scalar values (including empty string) have cardinality 1.
|
@@ -141,20 +252,20 @@ class CardinalityValidatable
|
|
141
252
|
# validates_single_cardinality_of :field
|
142
253
|
end
|
143
254
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
255
|
+
>> record = CardinalityValidatable.new
|
256
|
+
=> #<CardinalityValidatable:0x007fe3cbc632c8>
|
257
|
+
>> record.field = "foo"
|
258
|
+
=> "foo"
|
259
|
+
>> record.valid?
|
260
|
+
=> true
|
261
|
+
>> record.field = ["foo"]
|
262
|
+
=> ["foo"]
|
263
|
+
>> record.valid?
|
264
|
+
=> true
|
265
|
+
>> record.field = ["foo", "bar"]
|
266
|
+
=> ["foo", "bar"]
|
267
|
+
>> record.valid?
|
268
|
+
=> false
|
269
|
+
>> puts record.errors.full_messages
|
270
|
+
Field has the wrong cardinality (should have 1 value(s))
|
160
271
|
```
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'hydra/validations/enumerable_behavior'
|
2
|
+
module Hydra
|
3
|
+
module Validations
|
4
|
+
class PresenceValidator < ActiveModel::Validations::PresenceValidator
|
5
|
+
def validate_each(record, attribute, values)
|
6
|
+
values = Array.wrap(values)
|
7
|
+
record.errors.add(attribute, :blank, options) if values.blank? || values.any?(&:blank?)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
module HelperMethods
|
11
|
+
def validates_presence_of *attr_names
|
12
|
+
validates_with PresenceValidator, _merge_attributes(attr_names)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hydra::Validations::PresenceValidator do
|
4
|
+
let(:validatable) do
|
5
|
+
Class.new do
|
6
|
+
def self.name
|
7
|
+
'Validatable'
|
8
|
+
end
|
9
|
+
include ActiveModel::Validations
|
10
|
+
include Hydra::Validations
|
11
|
+
attr_accessor :an_attribute
|
12
|
+
validates_presence_of :an_attribute, message: "Can't have blank values"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'validation scenarios' do
|
17
|
+
subject { validatable.new }
|
18
|
+
[
|
19
|
+
{ values: [], valid?: false } ,
|
20
|
+
{ values: [''], valid?: false } ,
|
21
|
+
{ values: nil, valid?: false },
|
22
|
+
{ values: '', valid?: false },
|
23
|
+
{ values: ['work', ''], valid?: false },
|
24
|
+
{ values: ['work', nil], valid?: false },
|
25
|
+
{ values: ['work'], valid?: true },
|
26
|
+
{ values: 'work', valid?: true }
|
27
|
+
].each do |scenario|
|
28
|
+
it "will validate #{scenario.fetch(:values).inspect} as valid? == #{scenario.fetch(:valid?)}" do
|
29
|
+
subject.an_attribute = scenario.fetch(:values)
|
30
|
+
expect(subject.valid?).to eq(scenario.fetch(:valid?))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should add error message' do
|
35
|
+
subject.an_attribute = nil
|
36
|
+
subject.valid?
|
37
|
+
expect(subject.errors[:an_attribute]).to eq(["Can't have blank values"])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
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.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dchandekstark
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -88,6 +88,7 @@ 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/presence.rb
|
91
92
|
- lib/hydra/validations/uniqueness.rb
|
92
93
|
- lib/hydra/validations/version.rb
|
93
94
|
- spec/spec_helper.rb
|
@@ -96,6 +97,7 @@ files:
|
|
96
97
|
- spec/validations/format_validator_spec.rb
|
97
98
|
- spec/validations/helper_methods_spec.rb
|
98
99
|
- spec/validations/inclusion_validator_spec.rb
|
100
|
+
- spec/validations/presence_validator_spec.rb
|
99
101
|
- spec/validations/uniqueness_validator_spec.rb
|
100
102
|
homepage: https://github.com/duke-libraries/hydra-validations
|
101
103
|
licenses:
|
@@ -129,4 +131,5 @@ test_files:
|
|
129
131
|
- spec/validations/format_validator_spec.rb
|
130
132
|
- spec/validations/helper_methods_spec.rb
|
131
133
|
- spec/validations/inclusion_validator_spec.rb
|
134
|
+
- spec/validations/presence_validator_spec.rb
|
132
135
|
- spec/validations/uniqueness_validator_spec.rb
|