validates-structure 0.2.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 +7 -0
- data/LICENSE.txt +20 -0
- data/README.md +202 -0
- data/Rakefile +38 -0
- data/lib/validates-structure.rb +206 -0
- data/lib/validates-structure/version.rb +3 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fabdbd7d01016e5ded1f1cfe683c8e8f998ef94d
|
4
|
+
data.tar.gz: f2dc477eb6004acdac22e983e914b677f2929778
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0d74f74ac673327c6f134370c86ecfb210f8056974773d44c3fc43c71d164e5939c74a43cd70723a3857aa307403fb6dd020ce9b1ba3937e7309ee4428db2fe2
|
7
|
+
data.tar.gz: 8b790670773538b6890270f04d4ae621a2fa5e4c0bf36d49e5661bb11177f7956ea0d15ff9d07b1897a367b4580b2bc79264a563780e389dfb050552ca578b25
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 PugglePay
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
Validates Structure
|
2
|
+
===================
|
3
|
+
|
4
|
+
Validates Structure allows you to easily validate hash-structures using ActiveModel::Validations.
|
5
|
+
|
6
|
+
|
7
|
+
Dependencies
|
8
|
+
------------
|
9
|
+
The gem works for ActiveModel 4 and above.
|
10
|
+
|
11
|
+
|
12
|
+
Installation
|
13
|
+
------------
|
14
|
+
Simply add the gem to your gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'validates-structure'
|
18
|
+
```
|
19
|
+
|
20
|
+
and make sure your activemodel version is at least 4.0.0:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
gem 'activemodel', '>=4.0.0'
|
24
|
+
```
|
25
|
+
|
26
|
+
Remember to
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
require 'validates-structure'
|
30
|
+
```
|
31
|
+
|
32
|
+
at the top of the file when defining a new structure.
|
33
|
+
|
34
|
+
Canonical Usage Example
|
35
|
+
------------
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
require 'validates-structure'
|
39
|
+
|
40
|
+
class MyCanonicalValidator < ValidatesStructure::Validator
|
41
|
+
key 'foo', Hash do
|
42
|
+
key 'bar', Array do
|
43
|
+
value Integer, allow_nil: true
|
44
|
+
end
|
45
|
+
key 'baz', String, format: /\A[0-f]\z/
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
validator = MyCanonicalValidator.new({foo: {bar: [1, 2, nil, 'invalid']}})
|
50
|
+
validator.valid?
|
51
|
+
# => false
|
52
|
+
puts validator.errors.full_messages
|
53
|
+
# => /foo/bar[3] has class "String" but should be a "Integer"
|
54
|
+
# => /foo/baz is invalid
|
55
|
+
# => /foo/baz must not be nil
|
56
|
+
```
|
57
|
+
|
58
|
+
Quick facts about Validates Structure
|
59
|
+
-------------------------------------
|
60
|
+
* Validates Structure uses ActiveModel::Validations to validate your hash.
|
61
|
+
* Validates Structure automatically validates the type of each declared entry and will also give an error when undeclared keys are present.
|
62
|
+
* You can validate that a value are true or false by using the `Boolean` class (even though there are no Boolean class i Ruby).
|
63
|
+
* You can make compound hashes by setting a subclass to ValidatesStructure::Validator as the class in a key or value declaration.
|
64
|
+
* It doesn't matter if your structure uses symbols or strings as hash keys.
|
65
|
+
* Just like when validating attributes in a model, you can use your own custom validations.
|
66
|
+
|
67
|
+
Examples
|
68
|
+
--------
|
69
|
+
|
70
|
+
### Minimal example
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
class MySimpleValidator < ValidatesStructure::Validator
|
74
|
+
key 'apa', Integer
|
75
|
+
end
|
76
|
+
|
77
|
+
MySimpleValidator.new(apa: 3).valid?
|
78
|
+
# => true
|
79
|
+
```
|
80
|
+
|
81
|
+
### Boolean example
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
class MyBooleanValidator < ValidatesStructure::Validator
|
85
|
+
key 'apa', Boolean
|
86
|
+
end
|
87
|
+
|
88
|
+
MyBooleanValidator.new(apa: true).valid?
|
89
|
+
# => true
|
90
|
+
```
|
91
|
+
|
92
|
+
### Nested example
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
class MyNestedValidator < ValidatesStructure::Validator
|
96
|
+
key 'apa', Hash do
|
97
|
+
key 'bepa', String, presence: true
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
validator = MyNestedValidator.new(apa: { bepa: "" })
|
102
|
+
validator.valid?
|
103
|
+
# => false
|
104
|
+
puts validator.errors.full_messages
|
105
|
+
# => /apa/bepa can't be blank
|
106
|
+
```
|
107
|
+
|
108
|
+
### Array example
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
class MyArrayValidator < ValidatesStructure::Validator
|
112
|
+
key 'apa', Hash do
|
113
|
+
key 'bepa', Array do
|
114
|
+
value Integer
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
validator = MyArrayValidator.new(apa: { bepa: [1, 2, "3"] })
|
120
|
+
validator.valid?
|
121
|
+
# => true
|
122
|
+
puts validator.errors.full_messages
|
123
|
+
# => /apa/bepa[2] has class "String" but should be a "Integer"
|
124
|
+
```
|
125
|
+
|
126
|
+
### Compound example
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
class MyInnerValidator < ValidatesStructure::Validator
|
130
|
+
key 'bepa', Integer
|
131
|
+
end
|
132
|
+
|
133
|
+
class MyOuterValidator < ValidatesStructure::Validator
|
134
|
+
key 'apa', MyInnerValidator
|
135
|
+
end
|
136
|
+
|
137
|
+
MyOuterValidator.new(apa: { bepa: 3 }).valid?
|
138
|
+
# => true
|
139
|
+
```
|
140
|
+
|
141
|
+
### Custom validator example
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
class OddValidator < ActiveModel::EachValidator
|
145
|
+
def validate_each(record, attribute, value)
|
146
|
+
record.errors.add attribute, "can't be even." if value.even?
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class MyCustomValidator < ValidatesStructure::Validator
|
151
|
+
key 'apa', Integer, odd: true
|
152
|
+
end
|
153
|
+
|
154
|
+
MyCustomValidator.new(apa: 3).valid?
|
155
|
+
# => true
|
156
|
+
```
|
157
|
+
|
158
|
+
|
159
|
+
Documentation
|
160
|
+
-------------
|
161
|
+
This documentation is about the modules, classes, methods and options of ValidatesStructure. For documentation on ActiveModel::Validations see [the ActiveModel documentation.](http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates)
|
162
|
+
|
163
|
+
### ValidatesStructure::Validator
|
164
|
+
|
165
|
+
#### self.key(index, klass, validations={}, &block)
|
166
|
+
Sets up a requirement on the form ```'index' => klass``` that are validated with _validations_ and containing children on the form specified in _&block_.
|
167
|
+
|
168
|
+
**Parameters**
|
169
|
+
|
170
|
+
_index_ - The string or symbol by which to retrieve the value
|
171
|
+
|
172
|
+
_klass_ - The required class of the value. If klass is a subclass of ValidatesStructure::Validator then the value is validated as specified in its definition.
|
173
|
+
|
174
|
+
_validations_ - A hash with [ActiveModel:Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html) on the same format as for the [validates](http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates) method.
|
175
|
+
|
176
|
+
_&block_ - A block of nested _key_ and/or _value_ declarations. Only applicable if klass is an Array or Hashe.
|
177
|
+
|
178
|
+
|
179
|
+
#### self.value(klass, validations={},&block)
|
180
|
+
Sets up a requirement like self.key but without an index. Useful for structures that are accessed by a numeric index such as Arrays.
|
181
|
+
|
182
|
+
**Parameters**
|
183
|
+
|
184
|
+
_klass_ - The required class of the value. If klass is a subclass of ValidatesStructure::Validator then the value is validated as specified in its definition.
|
185
|
+
|
186
|
+
_validations_ - A hash with [ActiveModel:Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html) on the same format as for the [validates](http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates) method.
|
187
|
+
|
188
|
+
_&block_ - A block of nested _key_ and/or _value_ declarations. Only applicable if klass is an Array or Hashe.
|
189
|
+
|
190
|
+
|
191
|
+
Some History
|
192
|
+
------------
|
193
|
+
This project was initiated by the good fellows at [PugglePay](https://github.com/PugglePay) who felt there should be some easy, familiar way of validating their incoming json requests and wanted to share their solution with the world.
|
194
|
+
|
195
|
+
|
196
|
+
Contributing
|
197
|
+
------------
|
198
|
+
1. Fork the project
|
199
|
+
2. Create a feature branch (git checkout -b my-new-feature)
|
200
|
+
3. Commit your changes (git commit -am 'Add some feature')
|
201
|
+
4. Push branch to remote (git push origin my-new-feature)
|
202
|
+
5. Make a Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'ValidatesStructure'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
|
30
|
+
Rake::TestTask.new(:test) do |t|
|
31
|
+
t.libs << 'lib'
|
32
|
+
t.libs << 'test'
|
33
|
+
t.pattern = 'test/**/*_test.rb'
|
34
|
+
t.verbose = false
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
task :default => :test
|
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module ValidatesStructure
|
5
|
+
|
6
|
+
class Validator
|
7
|
+
include ActiveModel::Validations
|
8
|
+
|
9
|
+
class_attribute :keys, instance_writer: false
|
10
|
+
class_attribute :values, instance_writer: false
|
11
|
+
class_attribute :nested_validators, instance_writer: false
|
12
|
+
|
13
|
+
attr_accessor :keys
|
14
|
+
|
15
|
+
def initialize(hash)
|
16
|
+
self.class.initialize_class_attributes
|
17
|
+
self.keys = []
|
18
|
+
|
19
|
+
return unless hash.is_a?(Hash)
|
20
|
+
|
21
|
+
hash.each do |key, value|
|
22
|
+
self.keys << key.to_s
|
23
|
+
send "#{key}=", value if respond_to? "#{key}="
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.key(key, klass, validations={}, &block)
|
28
|
+
initialize_class_attributes
|
29
|
+
key = key.to_s
|
30
|
+
|
31
|
+
if klass.class != Class
|
32
|
+
raise ArgumentError.new("Types must be given as classes")
|
33
|
+
end
|
34
|
+
unless @nested_array_key.nil?
|
35
|
+
raise ArgumentError.new("Key can not only appear within a block of a key of type Array")
|
36
|
+
end
|
37
|
+
if keys.include?(key)
|
38
|
+
raise ArgumentError.new("Dublicate key \"#{key}\"")
|
39
|
+
end
|
40
|
+
|
41
|
+
keys << key
|
42
|
+
attr_accessor key
|
43
|
+
|
44
|
+
validations = prepare_validations(klass, validations, &block)
|
45
|
+
validates key, validations
|
46
|
+
|
47
|
+
nest_dsl(klass, key, &block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.value(klass, validations={}, &block)
|
51
|
+
initialize_class_attributes
|
52
|
+
|
53
|
+
if klass.class != Class
|
54
|
+
raise ArgumentError.new("Types must be given as classes")
|
55
|
+
end
|
56
|
+
if @nested_array_key.nil?
|
57
|
+
raise ArgumentError.new("Value can only appear within the block of a key of Array type")
|
58
|
+
end
|
59
|
+
if values[@nested_array_key]
|
60
|
+
raise ArgumentError.new("Value can only appear once within a block")
|
61
|
+
end
|
62
|
+
values[@nested_array_key] = klass
|
63
|
+
|
64
|
+
validations = prepare_validations(klass, validations, &block)
|
65
|
+
validates @nested_array_key, enumerable: validations
|
66
|
+
nest_dsl(klass, @nested_array_key, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.human_attribute_name(attr, *)
|
70
|
+
"/#{attr}"
|
71
|
+
end
|
72
|
+
|
73
|
+
validate do
|
74
|
+
(keys - self.class.keys).each do |key|
|
75
|
+
errors.add(key, "is not a known key")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
protected
|
80
|
+
|
81
|
+
def self.initialize_class_attributes
|
82
|
+
self.keys ||= []
|
83
|
+
self.values ||= {}
|
84
|
+
self.nested_validators ||= {}
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.prepare_validations(klass, validations, &block)
|
88
|
+
validations = validations.dup
|
89
|
+
validations[:klass] = { klass: (klass.ancestors.include?(Validator) ? Hash : klass) }
|
90
|
+
unless validations[:allow_nil] == true || validations[:allow_blank] == true
|
91
|
+
if klass == String
|
92
|
+
validations[:not_blank] = true
|
93
|
+
else
|
94
|
+
validations[:not_nil] = true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
validations[:nested] = true if block_given? || klass.ancestors.include?(Validator)
|
98
|
+
validations
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.nest_dsl(klass, key, &block)
|
102
|
+
if klass.ancestors.include?(Validator)
|
103
|
+
self.nested_validators[key] = klass
|
104
|
+
elsif block_given?
|
105
|
+
case
|
106
|
+
when klass == Hash
|
107
|
+
klass_name = "Annonimous#{ key.to_s.camelize }Validator#{SecureRandom.uuid.tr('-','')}"
|
108
|
+
const_set(klass_name, Class.new(self.superclass))
|
109
|
+
validator = const_get(klass_name)
|
110
|
+
validator.instance_eval(&block)
|
111
|
+
self.nested_validators[key] = validator
|
112
|
+
when klass == Array
|
113
|
+
@nested_array_key = key
|
114
|
+
yield
|
115
|
+
@nested_array_key = nil
|
116
|
+
else
|
117
|
+
raise ArgumentError.new("Didn't expect a block for the type \"#{klass}\"")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.model_name
|
123
|
+
ActiveModel::Name.new(self, nil, "temp")
|
124
|
+
end
|
125
|
+
|
126
|
+
class Boolean
|
127
|
+
end
|
128
|
+
|
129
|
+
class KlassValidator < ActiveModel::EachValidator
|
130
|
+
def validate_each(record, attribute, value)
|
131
|
+
return if value.nil?
|
132
|
+
klass = options[:klass]
|
133
|
+
if klass == Boolean
|
134
|
+
unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
135
|
+
record.errors.add attribute, "has class \"#{value.class}\" but should be boolean"
|
136
|
+
end
|
137
|
+
elsif !(value.is_a?(klass))
|
138
|
+
record.errors.add attribute, "has class \"#{value.class}\" but should be a \"#{klass}\""
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class NotNilValidator < ActiveModel::EachValidator
|
144
|
+
def validate_each(record, attribute, value)
|
145
|
+
if value.nil?
|
146
|
+
record.errors.add attribute, "must not be nil"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class NotBlankValidator < ActiveModel::EachValidator
|
152
|
+
def validate_each(record, attribute, value)
|
153
|
+
if value.blank?
|
154
|
+
record.errors.add attribute, "must not be empty"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
class NestedValidator < ActiveModel::EachValidator
|
160
|
+
def validate_each(record, attribute, value)
|
161
|
+
return unless value.is_a?(Hash)
|
162
|
+
return if record.errors.keys.map(&:to_s).include?(attribute)
|
163
|
+
|
164
|
+
validator = record.class.nested_validators[attribute]
|
165
|
+
return if validator.nil?
|
166
|
+
|
167
|
+
nested = validator.new(value)
|
168
|
+
nested.valid?
|
169
|
+
nested.errors.each do |nested_attribute, message|
|
170
|
+
record.errors.add("#{attribute}/#{nested_attribute}", message)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
class EnumerableValidator < ActiveModel::EachValidator
|
176
|
+
# Validates each value in an enumerable class using ActiveModel validations.
|
177
|
+
# Adapted from a snippet by Milovan Zogovic (http://stackoverflow.com/a/12744945)
|
178
|
+
def validate_each(record, attribute, values)
|
179
|
+
return unless values.respond_to?(:each_with_index)
|
180
|
+
values.each_with_index do |value, index|
|
181
|
+
options.each do |key, args|
|
182
|
+
validator_options = { attributes: attribute }
|
183
|
+
validator_options.merge!(args) if args.is_a?(Hash)
|
184
|
+
|
185
|
+
next if value.nil? && validator_options[:allow_nil]
|
186
|
+
next if value.blank? && validator_options[:allow_blank]
|
187
|
+
next if key.to_s == "allow_nil"
|
188
|
+
next if key.to_s == "allow_blank"
|
189
|
+
|
190
|
+
validator_class_name = "#{key.to_s.camelize}Validator"
|
191
|
+
validator_class = self.class.parent.const_get(validator_class_name)
|
192
|
+
validator = validator_class.new(validator_options)
|
193
|
+
|
194
|
+
# TODO: There should be a better way!
|
195
|
+
tmp_record = record.dup
|
196
|
+
validator.validate_each(tmp_record, attribute, value)
|
197
|
+
tmp_record.errors.each do |nested_attribute, error|
|
198
|
+
indexed_attribute = nested_attribute.to_s.sub(/^#{attribute}/, "#{attribute}[#{index}]")
|
199
|
+
record.errors.add(indexed_attribute, error)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: validates-structure
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Magnus Rex
|
8
|
+
- Daniel Ström
|
9
|
+
- Jean-Louis Giordano
|
10
|
+
- Patrik Kårlin
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
date: 2014-07-11 00:00:00.000000000 Z
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: activemodel
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 4.1.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 4.1.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - '>='
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: debugger
|
46
|
+
requirement: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: guard
|
60
|
+
requirement: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
type: :development
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: guard-rspec
|
74
|
+
requirement: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
description: Uses the power and familiarity of ActiveModel::Validations to validate
|
87
|
+
hash structures. Designed for detecting and providing feedback on bad requests to
|
88
|
+
your RESTful Web Service.
|
89
|
+
email:
|
90
|
+
- dev@pugglepay.com
|
91
|
+
executables: []
|
92
|
+
extensions: []
|
93
|
+
extra_rdoc_files: []
|
94
|
+
files:
|
95
|
+
- lib/validates-structure/version.rb
|
96
|
+
- lib/validates-structure.rb
|
97
|
+
- LICENSE.txt
|
98
|
+
- Rakefile
|
99
|
+
- README.md
|
100
|
+
homepage: https://github.com/PugglePay/validates-structure
|
101
|
+
licenses: []
|
102
|
+
metadata: {}
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - '>='
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
requirements: []
|
118
|
+
rubyforge_project:
|
119
|
+
rubygems_version: 2.0.3
|
120
|
+
signing_key:
|
121
|
+
specification_version: 4
|
122
|
+
summary: ActiveModel validations for nested structures like params.
|
123
|
+
test_files: []
|
124
|
+
has_rdoc:
|