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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6cd9dc181595609320187b6967b7419c584e5592
4
- data.tar.gz: e87ae57ed9847709bccd5979eee498381707cc13
3
+ metadata.gz: 5e3b8f594ffb78eea70a27d91d92ed195988ae54
4
+ data.tar.gz: 1d2abb83db312b502a3570bd428a90e13d355750
5
5
  SHA512:
6
- metadata.gz: 45b9a25dd9f59461d336b8877e14371f67ef764ed0b879960f375f97e60236a646c29cef36660703598a2fe3ac46f6f7a7a0ea2ee1be020ea6552e94c914bfa7
7
- data.tar.gz: 0212d9e7f159ddbacf0a291b4a80a91f95659aa95474c7cff67e337e57132fb37d2f39e2be660c4cfaaa0f856d51d62884c715196ca6b061522645e8c154aa23
6
+ metadata.gz: 77946326c106d26eef65cc9e41380a5a2eb01bab261f637dafb6400e84b710b31b2d3f04b22b7c8ba426a62043270708ebe78156bb467b904cf64b3175accdbd
7
+ data.tar.gz: 6084c27aaf6326df5adc5216b3466ecce67d67d0558cab7a0993c8fce488f8c263fe4ee5011cfd66d152b121c13593c95e803fc218e84fe844fab8784941608d
@@ -2,3 +2,4 @@ Contributors to this project:
2
2
 
3
3
  * David Chandek-Stark
4
4
  * Jeremy Friesen
5
+ * Rajesh Balekai
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
  [![Build Status](https://travis-ci.org/projecthydra-labs/hydra-validations.svg?branch=master)](https://travis-ci.org/projecthydra-labs/hydra-validations)
7
5
  [![Gem Version](https://badge.fury.io/rb/hydra-validations.svg)](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 the ActiveModel::Validations::FormatValidator, adding EnumerableBehavior.
130
+ Extends `ActiveModel::Validations::FormatValidator`, adding EnumerableBehavior.
37
131
 
38
- See documentation for ActiveModel::Validations::FormatValidator for usage and options.
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
- > v = FormatValidatable.new
51
- => #<FormatValidatable:0x007ffc55175300>
52
- > v.field = ["foo", "bar"]
53
- => ["foo", "bar"]
54
- > v.valid?
55
- => true
56
- > v.field = ["foo1", "bar2"]
57
- => ["foo1", "bar2"]
58
- > v.valid?
59
- => false
60
- > v.errors[:field]
61
- => ["value \"foo1\" is invalid", "value \"bar2\" is invalid"]
62
- > v.errors.full_messages
63
- => ["Field value \"foo1\" is invalid", "Field value \"bar2\" is invalid"]
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, adding EnumerableBehavior.
169
+ Extends `ActiveModel::Validations::InclusionValidator`, adding EnumerableBehavior.
69
170
 
70
- See documentation for ActiveModel::Validations::InclusionValidator for usage and options.
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
- > v = InclusionValidatable.new
83
- => #<InclusionValidatable:0x007ffc53079318>
84
- > v.field = ["foo", "bar"]
85
- => ["foo", "bar"]
86
- > v.valid?
87
- => true
88
- > v.field = ["foo", "bar", "spam", "eggs"]
89
- => ["foo", "bar", "spam", "eggs"]
90
- > v.valid?
91
- => false
92
- > v.errors[:field]
93
- => ["value \"spam\" is not included in the list", "value \"eggs\" is not included in the list"]
94
- > v.errors.full_messages
95
- => ["Field value \"spam\" is not included in the list", "Field value \"eggs\" is not included in the list"]
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 is a subclass of ActiveModel::Validations::LengthValidator which
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. Hence,
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
- > CardinalityValidatable.validators
145
- => [#<Hydra::Validations::CardinalityValidator:0x007fb91d1e9460 @attributes=[:field], @options={:is=>1}>]
146
- > v = Validatable.new
147
- => #<Validatable:0x007fb91d1c9188>
148
- > v.field = "foo"
149
- => "foo"
150
- > v.valid?
151
- => true
152
- > v.field = ["foo"]
153
- => ["foo"]
154
- > v.valid?
155
- => true
156
- > v.field = ["foo", "bar"]
157
- => ["foo", "bar"]
158
- > v.valid?
159
- => false
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
@@ -1,5 +1,5 @@
1
1
  module Hydra
2
2
  module Validations
3
- VERSION = "0.4.0"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  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.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: 2014-09-09 00:00:00.000000000 Z
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