hydra-validations 0.0.1 → 0.1.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: a47a19ff9228aa10cfe83244e932a14d1e7de081
4
- data.tar.gz: 48f15f4febd8af91c1c31277c36e8bb8b3d2d062
3
+ metadata.gz: 435663a78ed5e8ae4eed2d29cebbee6860792ed2
4
+ data.tar.gz: 85cf53d256c12174cda539c5193afff0a0e08a8a
5
5
  SHA512:
6
- metadata.gz: 2eda85501b41be48d7a016382dc37ed5bf9313a25813f6ca71f775adc75e94ac7d472a6aa7ce303a1c8718635baebb9e6c9ba2d827ecc236437c44f4eff14bef
7
- data.tar.gz: 54bdcb0cba015b4341f3410b43f2e9c2ee8b95d95069e34fc65f5e8a2194beda8cdd87dc94a9e7e3ace81529e001dff0af22d64b9a0784cc750dc12b8bac93cf
6
+ metadata.gz: cb3a7917caf907655fdfdcb3f1f304294c1cd4ea32abd73792b4301ac5b889b07a5c88e78c5519d8de86666c6d7419559fc6cbe3e82345cc81d16de833f9dd35
7
+ data.tar.gz: 906c190556c2aecb9ecd23c9dc123398551725f032b0616481d497d956b5382ce56c116da718b21d882641de370348e2d9085a0a3a0e68b57be913db79c5b5cb
data/.gitignore CHANGED
@@ -1,5 +1,5 @@
1
- .rspec
2
1
  /tmp
3
2
  /spec/tmp
4
3
  /.bundle
4
+ /pkg
5
5
  Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1
@@ -0,0 +1,116 @@
1
+ # How to Contribute
2
+
3
+ We want your help to make Project Hydra great.
4
+ There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.
5
+
6
+ ## Hydra Project Intellectual Property Licensing and Ownership
7
+
8
+ All code contributors must have an Individual Contributor License Agreement (iCLA) on file with the Hydra Project Steering Group.
9
+ If the contributor works for an institution, the institution must have a Corporate Contributor License Agreement (cCLA) on file.
10
+
11
+ https://wiki.duraspace.org/display/hydra/Hydra+Project+Intellectual+Property+Licensing+and+Ownership
12
+
13
+ You should also add yourself to the `CONTRIBUTORS.md` file in the root of the project.
14
+
15
+ ## Contribution Tasks
16
+
17
+ * Reporting Issues
18
+ * Making Changes
19
+ * Submitting Changes
20
+ * Merging Changes
21
+
22
+ ### Reporting Issues
23
+
24
+ * Make sure you have a [GitHub account](https://github.com/signup/free)
25
+ * Submit a [Github issue](./issues) by:
26
+ * Clearly describing the issue
27
+ * Provide a descriptive summary
28
+ * Explain the expected behavior
29
+ * Explain the actual behavior
30
+ * Provide steps to reproduce the actual behavior
31
+
32
+ ### Making Changes
33
+
34
+ * Fork the repository on GitHub
35
+ * Create a topic branch from where you want to base your work.
36
+ * This is usually the master branch.
37
+ * To quickly create a topic branch based on master; `git branch fix/master/my_contribution master`
38
+ * Then checkout the new branch with `git checkout fix/master/my_contribution`.
39
+ * Please avoid working directly on the `master` branch.
40
+ * You may find the [hub suite of commands](https://github.com/defunkt/hub) helpful
41
+ * Make commits of logical units.
42
+ * Your commit should include a high level description of your work in HISTORY.textile
43
+ * Check for unnecessary whitespace with `git diff --check` before committing.
44
+ * Make sure your commit messages are [well formed](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
45
+ * If you created an issue, you can close it by including "Closes #issue" in your commit message. See [Github's blog post for more details](https://github.com/blog/1386-closing-issues-via-commit-messages)
46
+
47
+ ```
48
+ Present tense short summary (50 characters or less)
49
+
50
+ More detailed description, if necessary. It should be wrapped to 72
51
+ characters. Try to be as descriptive as you can, even if you think that
52
+ the commit content is obvious, it may not be obvious to others. You
53
+ should add such description also if it's already present in bug tracker,
54
+ it should not be necessary to visit a webpage to check the history.
55
+
56
+ Include Closes #<issue-number> when relavent.
57
+
58
+ Description can have multiple paragraphs and you can use code examples
59
+ inside, just indent it with 4 spaces:
60
+
61
+ class PostsController
62
+ def index
63
+ respond_with Post.limit(10)
64
+ end
65
+ end
66
+
67
+ You can also add bullet points:
68
+
69
+ - you can use dashes or asterisks
70
+
71
+ - also, try to indent next line of a point for readability, if it's too
72
+ long to fit in 72 characters
73
+ ```
74
+
75
+ * Make sure you have added the necessary tests for your changes.
76
+ * Run _all_ the tests to assure nothing else was accidentally broken.
77
+ * When you are ready to submit a pull request
78
+
79
+ ### Submitting Changes
80
+
81
+ [Detailed Walkthrough of One Pull Request per Commit](http://ndlib.github.io/practices/one-commit-per-pull-request/)
82
+
83
+ * Read the article ["Using Pull Requests"](https://help.github.com/articles/using-pull-requests) on GitHub.
84
+ * Make sure your branch is up to date with its parent branch (i.e. master)
85
+ * `git checkout master`
86
+ * `git pull --rebase`
87
+ * `git checkout <your-branch>`
88
+ * `git rebase master`
89
+ * It is likely a good idea to run your tests again.
90
+ * Squash the commits for your branch into one commit
91
+ * `git rebase --interactive HEAD~<number-of-commits>` ([See Github help](https://help.github.com/articles/interactive-rebase))
92
+ * To determine the number of commits on your branch: `git log master..<your-branch> --oneline | wc -l`
93
+ * Squashing your branch's changes into one commit is "good form" and helps the person merging your request to see everything that is going on.
94
+ * Push your changes to a topic branch in your fork of the repository.
95
+ * Submit a pull request from your fork to the project.
96
+
97
+ ### Merging Changes
98
+
99
+ * It is considered "poor from" to merge your own request.
100
+ * Please take the time to review the changes and get a sense of what is being changed. Things to consider:
101
+ * Does the commit message explain what is going on?
102
+ * Does the code changes have tests? _Not all changes need new tests, some changes are refactorings_
103
+ * Does the commit contain more than it should? Are two separate concerns being addressed in one commit?
104
+ * Did the Travis tests complete successfully?
105
+ * If you are uncertain, bring other contributors into the conversation by creating a comment that includes their @username.
106
+ * If you like the pull request, but want others to chime in, create a +1 comment and tag a user.
107
+
108
+ ## New Developers
109
+ A great way to get new developers involved and to learn the process is to have them go through the Hierarchy of Promises and create a pull request to improve it.
110
+
111
+ # Additional Resources
112
+
113
+ * [General GitHub documentation](http://help.github.com/)
114
+ * [GitHub pull request documentation](http://help.github.com/send-pull-requests/)
115
+ * [Pro Git](http://git-scm.com/book) is both a free and excellent book about Git.
116
+ * [A Git Config for Contributing](http://ndlib.github.io/practices/my-typical-per-project-git-config/)
@@ -0,0 +1,3 @@
1
+ Contributors to this project:
2
+
3
+ * David Chandek-Stark
data/LICENSE CHANGED
@@ -1,201 +1,14 @@
1
- Apache License
2
- Version 2.0, January 2004
3
- http://www.apache.org/licenses/
1
+ Copyright 2014 Duke University Libraries
2
+ Additional copyright may be held by others, as reflected in the commit log.
4
3
 
5
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
6
7
 
7
- 1. Definitions.
8
+ http://www.apache.org/licenses/LICENSE-2.0
8
9
 
9
- "License" shall mean the terms and conditions for use, reproduction,
10
- and distribution as defined by Sections 1 through 9 of this document.
11
-
12
- "Licensor" shall mean the copyright owner or entity authorized by
13
- the copyright owner that is granting the License.
14
-
15
- "Legal Entity" shall mean the union of the acting entity and all
16
- other entities that control, are controlled by, or are under common
17
- control with that entity. For the purposes of this definition,
18
- "control" means (i) the power, direct or indirect, to cause the
19
- direction or management of such entity, whether by contract or
20
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
- outstanding shares, or (iii) beneficial ownership of such entity.
22
-
23
- "You" (or "Your") shall mean an individual or Legal Entity
24
- exercising permissions granted by this License.
25
-
26
- "Source" form shall mean the preferred form for making modifications,
27
- including but not limited to software source code, documentation
28
- source, and configuration files.
29
-
30
- "Object" form shall mean any form resulting from mechanical
31
- transformation or translation of a Source form, including but
32
- not limited to compiled object code, generated documentation,
33
- and conversions to other media types.
34
-
35
- "Work" shall mean the work of authorship, whether in Source or
36
- Object form, made available under the License, as indicated by a
37
- copyright notice that is included in or attached to the work
38
- (an example is provided in the Appendix below).
39
-
40
- "Derivative Works" shall mean any work, whether in Source or Object
41
- form, that is based on (or derived from) the Work and for which the
42
- editorial revisions, annotations, elaborations, or other modifications
43
- represent, as a whole, an original work of authorship. For the purposes
44
- of this License, Derivative Works shall not include works that remain
45
- separable from, or merely link (or bind by name) to the interfaces of,
46
- the Work and Derivative Works thereof.
47
-
48
- "Contribution" shall mean any work of authorship, including
49
- the original version of the Work and any modifications or additions
50
- to that Work or Derivative Works thereof, that is intentionally
51
- submitted to Licensor for inclusion in the Work by the copyright owner
52
- or by an individual or Legal Entity authorized to submit on behalf of
53
- the copyright owner. For the purposes of this definition, "submitted"
54
- means any form of electronic, verbal, or written communication sent
55
- to the Licensor or its representatives, including but not limited to
56
- communication on electronic mailing lists, source code control systems,
57
- and issue tracking systems that are managed by, or on behalf of, the
58
- Licensor for the purpose of discussing and improving the Work, but
59
- excluding communication that is conspicuously marked or otherwise
60
- designated in writing by the copyright owner as "Not a Contribution."
61
-
62
- "Contributor" shall mean Licensor and any individual or Legal Entity
63
- on behalf of whom a Contribution has been received by Licensor and
64
- subsequently incorporated within the Work.
65
-
66
- 2. Grant of Copyright License. Subject to the terms and conditions of
67
- this License, each Contributor hereby grants to You a perpetual,
68
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
- copyright license to reproduce, prepare Derivative Works of,
70
- publicly display, publicly perform, sublicense, and distribute the
71
- Work and such Derivative Works in Source or Object form.
72
-
73
- 3. Grant of Patent License. Subject to the terms and conditions of
74
- this License, each Contributor hereby grants to You a perpetual,
75
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
- (except as stated in this section) patent license to make, have made,
77
- use, offer to sell, sell, import, and otherwise transfer the Work,
78
- where such license applies only to those patent claims licensable
79
- by such Contributor that are necessarily infringed by their
80
- Contribution(s) alone or by combination of their Contribution(s)
81
- with the Work to which such Contribution(s) was submitted. If You
82
- institute patent litigation against any entity (including a
83
- cross-claim or counterclaim in a lawsuit) alleging that the Work
84
- or a Contribution incorporated within the Work constitutes direct
85
- or contributory patent infringement, then any patent licenses
86
- granted to You under this License for that Work shall terminate
87
- as of the date such litigation is filed.
88
-
89
- 4. Redistribution. You may reproduce and distribute copies of the
90
- Work or Derivative Works thereof in any medium, with or without
91
- modifications, and in Source or Object form, provided that You
92
- meet the following conditions:
93
-
94
- (a) You must give any other recipients of the Work or
95
- Derivative Works a copy of this License; and
96
-
97
- (b) You must cause any modified files to carry prominent notices
98
- stating that You changed the files; and
99
-
100
- (c) You must retain, in the Source form of any Derivative Works
101
- that You distribute, all copyright, patent, trademark, and
102
- attribution notices from the Source form of the Work,
103
- excluding those notices that do not pertain to any part of
104
- the Derivative Works; and
105
-
106
- (d) If the Work includes a "NOTICE" text file as part of its
107
- distribution, then any Derivative Works that You distribute must
108
- include a readable copy of the attribution notices contained
109
- within such NOTICE file, excluding those notices that do not
110
- pertain to any part of the Derivative Works, in at least one
111
- of the following places: within a NOTICE text file distributed
112
- as part of the Derivative Works; within the Source form or
113
- documentation, if provided along with the Derivative Works; or,
114
- within a display generated by the Derivative Works, if and
115
- wherever such third-party notices normally appear. The contents
116
- of the NOTICE file are for informational purposes only and
117
- do not modify the License. You may add Your own attribution
118
- notices within Derivative Works that You distribute, alongside
119
- or as an addendum to the NOTICE text from the Work, provided
120
- that such additional attribution notices cannot be construed
121
- as modifying the License.
122
-
123
- You may add Your own copyright statement to Your modifications and
124
- may provide additional or different license terms and conditions
125
- for use, reproduction, or distribution of Your modifications, or
126
- for any such Derivative Works as a whole, provided Your use,
127
- reproduction, and distribution of the Work otherwise complies with
128
- the conditions stated in this License.
129
-
130
- 5. Submission of Contributions. Unless You explicitly state otherwise,
131
- any Contribution intentionally submitted for inclusion in the Work
132
- by You to the Licensor shall be under the terms and conditions of
133
- this License, without any additional terms or conditions.
134
- Notwithstanding the above, nothing herein shall supersede or modify
135
- the terms of any separate license agreement you may have executed
136
- with Licensor regarding such Contributions.
137
-
138
- 6. Trademarks. This License does not grant permission to use the trade
139
- names, trademarks, service marks, or product names of the Licensor,
140
- except as required for reasonable and customary use in describing the
141
- origin of the Work and reproducing the content of the NOTICE file.
142
-
143
- 7. Disclaimer of Warranty. Unless required by applicable law or
144
- agreed to in writing, Licensor provides the Work (and each
145
- Contributor provides its Contributions) on an "AS IS" BASIS,
146
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
- implied, including, without limitation, any warranties or conditions
148
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
- PARTICULAR PURPOSE. You are solely responsible for determining the
150
- appropriateness of using or redistributing the Work and assume any
151
- risks associated with Your exercise of permissions under this License.
152
-
153
- 8. Limitation of Liability. In no event and under no legal theory,
154
- whether in tort (including negligence), contract, or otherwise,
155
- unless required by applicable law (such as deliberate and grossly
156
- negligent acts) or agreed to in writing, shall any Contributor be
157
- liable to You for damages, including any direct, indirect, special,
158
- incidental, or consequential damages of any character arising as a
159
- result of this License or out of the use or inability to use the
160
- Work (including but not limited to damages for loss of goodwill,
161
- work stoppage, computer failure or malfunction, or any and all
162
- other commercial damages or losses), even if such Contributor
163
- has been advised of the possibility of such damages.
164
-
165
- 9. Accepting Warranty or Additional Liability. While redistributing
166
- the Work or Derivative Works thereof, You may choose to offer,
167
- and charge a fee for, acceptance of support, warranty, indemnity,
168
- or other liability obligations and/or rights consistent with this
169
- License. However, in accepting such obligations, You may act only
170
- on Your own behalf and on Your sole responsibility, not on behalf
171
- of any other Contributor, and only if You agree to indemnify,
172
- defend, and hold each Contributor harmless for any liability
173
- incurred by, or claims asserted against, such Contributor by reason
174
- of your accepting any such warranty or additional liability.
175
-
176
- END OF TERMS AND CONDITIONS
177
-
178
- APPENDIX: How to apply the Apache License to your work.
179
-
180
- To apply the Apache License to your work, attach the following
181
- boilerplate notice, with the fields enclosed by brackets "{}"
182
- replaced with your own identifying information. (Don't include
183
- the brackets!) The text should be enclosed in the appropriate
184
- comment syntax for the file format. We also recommend that a
185
- file or class name and description of purpose be included on the
186
- same "printed page" as the copyright notice for easier
187
- identification within third-party archives.
188
-
189
- Copyright {yyyy} {name of copyright owner}
190
-
191
- Licensed under the Apache License, Version 2.0 (the "License");
192
- you may not use this file except in compliance with the License.
193
- You may obtain a copy of the License at
194
-
195
- http://www.apache.org/licenses/LICENSE-2.0
196
-
197
- Unless required by applicable law or agreed to in writing, software
198
- distributed under the License is distributed on an "AS IS" BASIS,
199
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
- See the License for the specific language governing permissions and
201
- limitations under the License.
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
data/README.md CHANGED
@@ -1,7 +1,13 @@
1
1
  hydra-validations
2
2
  =======================
3
3
 
4
- Custom validations for Hydra applications based on ActiveModel::Validations.
4
+ Custom validators for Hydra applications based on ActiveModel::Validations.
5
+
6
+ ### Dependencies
7
+
8
+ * Ruby >= 1.9.3
9
+ * ActiveModel 4.x
10
+ * ActiveFedora 7.x
5
11
 
6
12
  ### Installation
7
13
 
@@ -17,16 +23,33 @@ and
17
23
  bundle install
18
24
  ```
19
25
 
20
- ### Usage
21
-
22
- To include helper methods:
23
-
24
- ```ruby
25
- include Hydra::Validations
26
- ```
26
+ ### Example
27
27
 
28
- For example:
28
+ With a PORO, we have to include ActiveModel::Validations.
29
+ ActiveRecord::Base and ActiveFedora::Base already include ActiveModel::Validations.
29
30
 
30
31
  ```ruby
31
- validates_single_cardinality_of :my_single_valued_attr
32
+ class Validatable
33
+ include ActiveModel::Validations
34
+ include Hydra::Validations
35
+ attr_accessor :field
36
+ validates :field, single_cardinality: true
37
+ end
38
+
39
+ > Validatable.validators
40
+ => [#<Hydra::Validations::SingleCardinalityValidator:0x007fb91d1e9460 @attributes=[:field], @options={}>]
41
+ > v = Validatable.new
42
+ => #<Validatable:0x007fb91d1c9188>
43
+ > v.field = "foo"
44
+ => "foo"
45
+ > v.valid?
46
+ => true
47
+ > v.field = ["foo"]
48
+ => ["foo"]
49
+ > v.valid?
50
+ => true
51
+ > v.field = ["foo", "bar"]
52
+ => ["foo", "bar"]
53
+ > v.valid?
54
+ => false
32
55
  ```
data/Rakefile CHANGED
@@ -1,2 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
2
3
 
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -6,12 +6,14 @@ require 'hydra/validations/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "hydra-validations"
8
8
  spec.version = Hydra::Validations::VERSION
9
+ spec.platform = Gem::Platform::RUBY
9
10
  spec.authors = ["dchandekstark"]
10
11
  spec.email = ["dchandekstark@gmail.com"]
11
12
  spec.summary = %q{Validations for Hydra applications, based on ActiveModel::Validations}
12
13
  spec.description = %q{Validations for Hydra applications, based on ActiveModel::Validations}
13
14
  spec.homepage = "https://github.com/duke-libraries/hydra-validations"
14
15
  spec.license = "APACHE2"
16
+ spec.required_ruby_version = ">= 1.9.3"
15
17
 
16
18
  spec.files = `git ls-files -z`.split("\x0")
17
19
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
@@ -19,6 +21,7 @@ Gem::Specification.new do |spec|
19
21
  spec.require_paths = ["lib", "app/validators"]
20
22
 
21
23
  spec.add_dependency "activemodel", "~> 4.0"
24
+ spec.add_dependency "active-fedora", "~> 7.0"
22
25
  spec.add_development_dependency "bundler", "~> 1.6"
23
26
  spec.add_development_dependency "rake"
24
27
  spec.add_development_dependency "rspec"
@@ -1,15 +1,16 @@
1
+ require "active_model"
1
2
  require "hydra/validations/version"
2
- require "hydra/validations/helper_methods"
3
3
 
4
4
  module Hydra
5
5
  module Validations
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
+ extend HelperMethods
9
10
  include HelperMethods
10
11
  end
11
12
 
12
13
  end
13
14
  end
14
15
 
15
- Dir[File.dirname(__FILE__) + "/validations/*validator.rb"].each { |file| require file }
16
+ Dir[File.dirname(__FILE__) + "/validations/*.rb"].each { |file| require file }
@@ -1,14 +1,26 @@
1
1
  #
2
2
  # SingleCardinalityValidator - validates that an enumerator value has size 0 or 1
3
3
  #
4
- # validates :myattr, single_cardinality: true
4
+ # validates :my_attr, single_cardinality: true
5
+ # validates_single_cardinality_of :my_attr
5
6
  #
6
- class SingleCardinalityValidator < ActiveModel::EachValidator
7
+ module Hydra
8
+ module Validations
7
9
 
8
- def validate_each(record, attribute, value)
9
- if value.respond_to?(:each)
10
- record.errors.add(attribute, "can't have more than one value") if value.size > 1
10
+ class SingleCardinalityValidator < ActiveModel::EachValidator
11
+ def validate_each(record, attribute, value)
12
+ if value.respond_to?(:each)
13
+ record.errors.add(attribute, "can't have more than one value") if value.size > 1
14
+ end
15
+ end
16
+ end
17
+
18
+ module HelperMethods
19
+ def validates_single_cardinality_of *attr_names
20
+ validates_with SingleCardinalityValidator, _merge_attributes(attr_names)
21
+ end
11
22
  end
12
- end
13
23
 
24
+ end
14
25
  end
26
+
@@ -0,0 +1,51 @@
1
+ module Hydra
2
+ module Validations
3
+ #
4
+ # UniquenessValidator - an ActiveFedora model validator
5
+ #
6
+ # Usage:
7
+ #
8
+ # validates :field, uniqueness: { solr_name: "field_ssim" }
9
+ # validates_uniqueness_of :field, solr_name: "field_ssim"
10
+ #
11
+ # Restrictions:
12
+ #
13
+ # - Accepts only one attribute (can have more than one UniquenessValidator on a model, however)
14
+ # - Attribute cannot be multi-valued (:multiple=>true option of `has_attributes')
15
+ # - :solr_name option must be present
16
+ #
17
+ # CAVEAT: The determination of uniqueness depends on a Solr query.
18
+ # False negatives (record invalid) may result if, for example,
19
+ # querying a Solr field of type "text".
20
+ #
21
+ class UniquenessValidator < ActiveModel::EachValidator
22
+
23
+ def initialize(options = {})
24
+ super
25
+ attributes.each do |attr|
26
+ raise ArgumentError, "Cannot validate uniqueness on a multi-valued attribute: #{attribute}." if options[:class].multiple?(attr)
27
+ end
28
+ end
29
+
30
+ def check_validity!
31
+ raise ArgumentError, "UniquenessValidator accepts only a single attribute: #{attribues}" if attributes.length > 1
32
+ raise ArgumentError, "UniquenessValidator requires the :solr_name option be present." unless options[:solr_name].present?
33
+ end
34
+
35
+ def validate_each(record, attribute, value)
36
+ conditions = {options[:solr_name] => value}
37
+ conditions.merge!("-id" => record.id) if record.persisted?
38
+ if record.class.exists? conditions
39
+ record.errors.add attribute, "has already been taken"
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ module HelperMethods
46
+ def validates_uniqueness_of *attr_names
47
+ validates_with UniquenessValidator, _merge_attributes(attr_names)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,5 +1,5 @@
1
1
  module Hydra
2
2
  module Validations
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -1,7 +1,4 @@
1
- $LOAD_PATH.unshift(File.expand_path('../../app/validators', __FILE__))
2
-
3
1
  require 'active_model'
4
- require 'active_support'
5
2
  require 'hydra/validations'
6
3
 
7
4
  RSpec.configure do |config|
@@ -25,7 +22,7 @@ RSpec.configure do |config|
25
22
  # Print the 10 slowest examples and example groups at the
26
23
  # end of the spec run, to help surface which specs are running
27
24
  # particularly slow.
28
- config.profile_examples = 10
25
+ # config.profile_examples = 10
29
26
 
30
27
  # Run specs in random order to surface order dependencies. If you find an
31
28
  # order dependency and want to debug it, you can fix the order by providing
@@ -25,7 +25,7 @@ shared_examples "it validates the single cardinality of the field" do
25
25
  end
26
26
  end
27
27
 
28
- describe SingleCardinalityValidator do
28
+ describe Hydra::Validations::SingleCardinalityValidator do
29
29
  before(:all) do
30
30
  class Validatable
31
31
  include ActiveModel::Validations
@@ -34,6 +34,7 @@ describe SingleCardinalityValidator do
34
34
  end
35
35
  end
36
36
  before(:each) { Validatable.clear_validators! }
37
+ after(:all) { Object.send(:remove_const, :Validatable) }
37
38
  subject { Validatable.new }
38
39
  describe ".validates" do
39
40
  before { Validatable.validates :field, single_cardinality: true }
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ require 'active_fedora'
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
+ describe Hydra::Validations::UniquenessValidator do
20
+
21
+ before(:all) do
22
+ class Validatable < ActiveFedora::Base
23
+ include Hydra::Validations
24
+ has_metadata name: 'descMetadata', type: ActiveFedora::QualifiedDublinCoreDatastream
25
+ has_attributes :title, datastream: 'descMetadata', multiple: false
26
+ has_attributes :creator, datastream: 'descMetadata', multiple: false
27
+ has_attributes :subject, datastream: 'descMetadata', multiple: true
28
+ end
29
+ end
30
+
31
+ after(:all) { Object.send(:remove_const, :Validatable) }
32
+
33
+ describe "exceptions" do
34
+ before { Validatable.clear_validators! }
35
+ it "cannot be used on a multi-valued attribute" do
36
+ expect { Validatable.validates :subject, uniqueness: { solr_name: "subject_ssim" } }.to raise_error
37
+ end
38
+ it "cannot be used on more than one attribute at a time" do
39
+ expect { Validatable.validates :title, :creator, uniqueness: { solr_name: "snafu_ssim" } }.to raise_error
40
+ end
41
+ it "cannot be used without the :solr_name option" do
42
+ expect { Validatable.validates :title, uniqueness: true }.to raise_error
43
+ end
44
+ end
45
+
46
+ describe "validation" do
47
+ subject { Validatable.new(pid: "foobar:1", title: "I am Unique!") }
48
+ let(:solr_name) { "title_ssi" }
49
+ before do
50
+ Validatable.clear_validators!
51
+ Validatable.validates_uniqueness_of :title, solr_name: solr_name
52
+ end
53
+ context "when the record is new" do
54
+ before { allow(subject).to receive(:persisted?) { false } }
55
+ it_behaves_like "it validates the uniqueness of the attribute value" do
56
+ let(:conditions) { {solr_name => subject.title} }
57
+ end
58
+ end
59
+ context "when the record is persisted" do
60
+ before { allow(subject).to receive(:persisted?) { true } }
61
+ it_behaves_like "it validates the uniqueness of the attribute value" do
62
+ let(:conditions) { {solr_name => subject.title, "-id" => subject.pid} }
63
+ end
64
+ end
65
+ end
66
+ 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.0.1
4
+ version: 0.1.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-08-15 00:00:00.000000000 Z
11
+ date: 2014-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: active-fedora
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '7.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '7.0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -74,17 +88,22 @@ extensions: []
74
88
  extra_rdoc_files: []
75
89
  files:
76
90
  - ".gitignore"
91
+ - ".rspec"
92
+ - ".travis.yml"
93
+ - CONTRIBUTING.md
94
+ - CONTRIBUTORS.md
77
95
  - Gemfile
78
96
  - LICENSE
79
97
  - README.md
80
98
  - Rakefile
81
99
  - hydra-validations.gemspec
82
100
  - lib/hydra/validations.rb
83
- - lib/hydra/validations/helper_methods.rb
84
101
  - lib/hydra/validations/single_cardinality_validator.rb
102
+ - lib/hydra/validations/uniqueness_validator.rb
85
103
  - lib/hydra/validations/version.rb
86
104
  - spec/spec_helper.rb
87
105
  - spec/validators/single_cardinality_validator_spec.rb
106
+ - spec/validators/uniqueness_validator_spec.rb
88
107
  homepage: https://github.com/duke-libraries/hydra-validations
89
108
  licenses:
90
109
  - APACHE2
@@ -98,7 +117,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
98
117
  requirements:
99
118
  - - ">="
100
119
  - !ruby/object:Gem::Version
101
- version: '0'
120
+ version: 1.9.3
102
121
  required_rubygems_version: !ruby/object:Gem::Requirement
103
122
  requirements:
104
123
  - - ">="
@@ -113,3 +132,4 @@ summary: Validations for Hydra applications, based on ActiveModel::Validations
113
132
  test_files:
114
133
  - spec/spec_helper.rb
115
134
  - spec/validators/single_cardinality_validator_spec.rb
135
+ - spec/validators/uniqueness_validator_spec.rb
@@ -1,14 +0,0 @@
1
- module Hydra
2
- module Validations
3
- module HelperMethods
4
- extend ActiveSupport::Concern
5
-
6
- module ClassMethods
7
- def validates_single_cardinality_of *attr_names
8
- validates_with SingleCardinalityValidator, _merge_attributes(attr_names)
9
- end
10
- end
11
-
12
- end
13
- end
14
- end