hydra-validations 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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