compel 0.3.2 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +112 -63
  3. data/compel.gemspec +1 -1
  4. data/lib/compel/builder/any.rb +13 -0
  5. data/lib/compel/builder/array.rb +1 -5
  6. data/lib/compel/builder/common.rb +17 -2
  7. data/lib/compel/builder/common_value.rb +0 -5
  8. data/lib/compel/builder/hash.rb +0 -4
  9. data/lib/compel/builder/methods.rb +5 -0
  10. data/lib/compel/builder/string.rb +1 -11
  11. data/lib/compel/coercion/coercion.rb +3 -8
  12. data/lib/compel/coercion/types/any.rb +13 -0
  13. data/lib/compel/coercion/types/json.rb +2 -0
  14. data/lib/compel/coercion/types/type.rb +5 -1
  15. data/lib/compel/errors.rb +1 -1
  16. data/lib/compel/validation/conditions/condition.rb +31 -0
  17. data/lib/compel/validation/conditions/format.rb +19 -0
  18. data/lib/compel/validation/conditions/in.rb +25 -0
  19. data/lib/compel/validation/conditions/is.rb +29 -0
  20. data/lib/compel/validation/conditions/length.rb +21 -0
  21. data/lib/compel/validation/conditions/max.rb +21 -0
  22. data/lib/compel/validation/conditions/max_length.rb +21 -0
  23. data/lib/compel/validation/conditions/min.rb +21 -0
  24. data/lib/compel/validation/conditions/min_length.rb +21 -0
  25. data/lib/compel/validation/result.rb +23 -0
  26. data/lib/compel/validation/validation.rb +62 -0
  27. data/lib/compel/validators/base.rb +4 -0
  28. data/lib/compel/validators/type_validator.rb +2 -4
  29. data/lib/compel/version.rb +1 -1
  30. data/lib/compel.rb +5 -12
  31. data/spec/compel/builder_spec.rb +72 -2
  32. data/spec/compel/coercion_spec.rb +25 -30
  33. data/spec/compel/compel_spec.rb +3 -3
  34. data/spec/compel/validation_spec.rb +65 -11
  35. metadata +16 -5
  36. data/lib/compel/exceptions/validation_error.rb +0 -7
  37. data/lib/compel/validation.rb +0 -60
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dd41d8ef8ee213b7c02d1ba4d465fa3d9e3afbca
4
- data.tar.gz: 7443f067c1f523c1b455b68f1257eda3abc1df06
3
+ metadata.gz: bef1b2e1274aa8234be2702abb7267fb7663de84
4
+ data.tar.gz: 2a5d3146d9b59f2aaf54c8e552b721434774011c
5
5
  SHA512:
6
- metadata.gz: 44c69252f56c16deb155cdfdc75f4da36bbf212f3cf114959f7b9d69eb9449c38bb9d3769aeb0ad10351ef6ae18362d3e1696a80bdfbe8ca9fc85e53953a01a6
7
- data.tar.gz: e66cda22c5cb242fbe548667dde04529fdd37b48c5049be7311420d03a2209fb3e2e5a5f7da1d6617b603bfa7b96ab536708d5ac1250e5d627dfb7b8272bfef2
6
+ metadata.gz: 6b29767783dd35c1c9783499ae9f9c26dc773f7e09d37fba395ebe1d83d5fa167f496d39de056a45d7217578a973d86101a63580415cc716dcbeafb1b9af9d94
7
+ data.tar.gz: 645a9ea31ccce72d524e38f98567d3153630af64475b0c0ad506fe85b7977bc93ce5bd76cd452e6276aecba09316f019736e852f3defb1fc9a80e5e34459e936
data/README.md CHANGED
@@ -4,13 +4,13 @@ Compel
4
4
  [![Code Climate](https://codeclimate.com/github/joaquimadraz/compel/badges/gpa.svg)](https://codeclimate.com/github/joaquimadraz/compel)
5
5
  [![Test Coverage](https://codeclimate.com/github/joaquimadraz/compel/badges/coverage.svg)](https://codeclimate.com/github/joaquimadraz/compel/coverage)
6
6
 
7
- Ruby Hash Coercion and Validation
7
+ Ruby Object Coercion and Validation
8
8
 
9
- This is a straight forward way to validate a Ruby Hash: just give an object and the schema.
9
+ This is a straight forward way to validate any Ruby object: just give an object and the schema.
10
10
 
11
- The motivation was to create an integration for [RestMyCase](https://github.com/goncalvesjoao/rest_my_case) and have validations before any business logic execution.
11
+ The motivation was to create an integration for [RestMyCase](https://github.com/goncalvesjoao/rest_my_case) to have validations before any business logic execution and to build a easy way coerce and validate params on [Sinatra](https://github.com/sinatra/sinatra).
12
12
 
13
- Based on the same principle from [Grape](https://github.com/ruby-grape/grape) framework and [sinatra-param](https://github.com/mattt/sinatra-param) gem to validate request params. The schema builder is based on [Joi](https://github.com/hapijs/joi).
13
+ The schema builder is based on [Joi](https://github.com/hapijs/joi).
14
14
 
15
15
  ### Usage
16
16
 
@@ -66,7 +66,7 @@ There are 4 ways to run validations:
66
66
 
67
67
  Method | Behaviour
68
68
  ------------- | -------------
69
- `#run` | Validates and returns an Hash with coerced params plus a `:errors` key with a _Rails like_ Hash of errors if any.
69
+ `#run` | Validates and returns a `Compel::Result` (see below)
70
70
  `#run!` | Validates and raises `Compel::InvalidObjectError` exception with the coerced params and errors.
71
71
  `#run?` | Validates and returns true or false.
72
72
  `schema#validate` | Check below
@@ -74,57 +74,111 @@ Method | Behaviour
74
74
  ==========================
75
75
 
76
76
  ### Schema Builder API
77
- - `Compel#array` *
78
- - `is(``array``)`
79
- - `#items(``schema``)`
80
- ```ruby
81
- * ex: [1, 2, 3], [{ a: 1, b: 2}, { a: 3, b: 4 }]
82
- ```
83
-
84
- - `Compel#hash` *
85
- - `#keys(``schema_hash``)`
86
- ```ruby
87
- * ex: { a: 1, b: 2, c: 3 }
88
- ```
89
-
90
- - `Compel.date` *
91
- - `#format(``ruby_date_format``)`
92
- - `iso8601`, set format to: `%Y-%m-%d`
93
-
94
- - `Compel.datetime & Compel.time` *
95
- - `#format(``ruby_date_format``)`
96
- - `#iso8601`, set format to: `%FT%T`
97
-
98
- - `Compel#string` **
99
- - `#format(``regexp``)`
100
- - `#min_length(``integer``)`
101
- - `#max_length(``integer``)`
102
-
103
- - `Compel#json` *
104
- ```ruby
105
- * ex: "{\"a\":1,\"b\":2,\"c\":3}"
106
- ```
107
-
108
- - `Compel#boolean` *
109
- ```ruby
110
- * ex: 1/0, true/false, 't'/'f', 'yes'/'no', 'y'/'n'
111
- ```
112
-
113
- - `Compel#integer` **
114
-
115
- - `Compel#float` **
116
-
117
- (\*) **Common methods**
118
- - `required`
119
- - `default(``value``)`
120
-
121
- (\*\*) **Common value methods**
122
- - `is(``value``)`
123
- - `in(``array``)`
124
- - `length(``integer``)`
125
- - `min(``value``)`
126
- - `max(``value``)`
127
77
 
78
+ #### Compel#any
79
+ `Any` referes to any type that is available to coerce with Compel.
80
+
81
+ **Methods**:
82
+ - `is(``value``)`
83
+ - `required`
84
+ - `default(``value``)`
85
+ - `length(``integer``)`
86
+ - `min_length(``integer``)`
87
+ - `max_length(``integer``)`
88
+
89
+ ==========================
90
+
91
+ #### Compel#array
92
+
93
+ **Methods**:
94
+ - `#items(``schema``)`
95
+
96
+ **Examples**:
97
+ ```ruby
98
+ . [1, 2, 3]
99
+ . [{ a: 1, b: 2}
100
+ . { a: 3, b: 4 }]
101
+ ```
102
+
103
+ ==========================
104
+
105
+ #### Compel#hash
106
+
107
+ **Methods**:
108
+ - `keys(``schema_hash``)`
109
+
110
+ **Examples**:
111
+ ```ruby
112
+ . { a: 1, b: 2, c: 3 }
113
+ ```
114
+
115
+ ==========================
116
+
117
+ #### Compel#date
118
+
119
+ **Methods**:
120
+ - `format(``ruby_date_format``)`
121
+ - `iso8601`, set format to: `%Y-%m-%d`
122
+
123
+ ==========================
124
+
125
+ #### Compel#datetime & Compel#time
126
+
127
+ **Methods**:
128
+ - `format(``ruby_date_format``)`
129
+ - `iso8601`, set format to: `%FT%T`
130
+
131
+ ==========================
132
+
133
+ #### Compel#json
134
+
135
+ **Examples**:
136
+ ```ruby
137
+ . "{\"a\":1,\"b\":2,\"c\":3}"
138
+ ```
139
+
140
+ ==========================
141
+
142
+ #### Compel#boolean
143
+
144
+ **Examples**:
145
+ ```ruby
146
+ . 1/0
147
+ . true/false
148
+ . 't'/'f'
149
+ . 'yes'/'no'
150
+ . 'y'/'n'
151
+ ```
152
+
153
+ ==========================
154
+
155
+ #### Compel#string
156
+
157
+ **Methods**:
158
+ - `in(``array``)`
159
+ - `min(``value``)`
160
+ - `max(``value``)`
161
+ - `format(``regexp``)`
162
+
163
+ ==========================
164
+
165
+ #### Compel#integer
166
+
167
+ **Methods**:
168
+ - `in(``array``)`
169
+ - `min(``value``)`
170
+ - `max(``value``)`
171
+
172
+ ==========================
173
+
174
+ #### Compel#float
175
+
176
+ **Methods**:
177
+ - `in(``array``)`
178
+ - `min(``value``)`
179
+ - `max(``value``)`
180
+
181
+ ==========================
128
182
 
129
183
  ### Schema Validate
130
184
 
@@ -199,23 +253,18 @@ class App < Sinatra::Base
199
253
 
200
254
  end
201
255
  ```
256
+
202
257
  ###Installation
203
258
 
204
259
  Add this line to your application's Gemfile:
205
260
 
206
- gem 'compel', '~> 0.2.0'
261
+ gem 'compel', '~> 0.3.4'
207
262
 
208
263
  And then execute:
209
264
 
210
265
  $ bundle
211
266
 
212
- ### TODO
213
-
214
- - Write Advanced Documentation (check specs for now ;)
215
- - Rails integration
216
- - [RestMyCase](https://github.com/goncalvesjoao/rest_my_case) integration
217
-
218
-
219
267
  ### Get in touch
268
+
220
269
  If you have any questions, write an issue or get in touch [@joaquimadraz](https://twitter.com/joaquimadraz)
221
270
 
data/compel.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |gem|
10
10
  gem.authors = ['Joaquim Adráz']
11
11
  gem.email = ['joaquim.adraz@gmail.com']
12
12
  gem.description = %q{Compel}
13
- gem.summary = %q{Ruby Hash Coercion and Validation}
13
+ gem.summary = %q{Ruby Object Coercion and Validation}
14
14
  gem.homepage = 'https://github.com/joaquimadraz/compel'
15
15
 
16
16
  gem.files = `git ls-files`.split($/)
@@ -0,0 +1,13 @@
1
+ module Compel
2
+ module Builder
3
+
4
+ class Any < Schema
5
+
6
+ def initialize
7
+ super(Coercion::Any)
8
+ end
9
+
10
+ end
11
+
12
+ end
13
+ end
@@ -17,14 +17,10 @@ module Compel
17
17
  end
18
18
 
19
19
  def is(value)
20
- options[:is] = Coercion.coerce!(value, ::Array)
20
+ options[:is] = Coercion.coerce!(value, Coercion::Array)
21
21
  self
22
22
  end
23
23
 
24
- def validate(object)
25
- Contract.new(object, self).validate
26
- end
27
-
28
24
  end
29
25
 
30
26
  end
@@ -3,8 +3,8 @@ module Compel
3
3
 
4
4
  module Common
5
5
 
6
- def length(value)
7
- options[:length] = Coercion.coerce!(value, ::Integer)
6
+ def is(value)
7
+ options[:is] = value
8
8
  self
9
9
  end
10
10
 
@@ -18,6 +18,21 @@ module Compel
18
18
  self
19
19
  end
20
20
 
21
+ def length(value)
22
+ options[:length] = Coercion.coerce!(value, Coercion::Integer)
23
+ self
24
+ end
25
+
26
+ def min_length(value)
27
+ options[:min_length] = Coercion.coerce!(value, Coercion::Integer)
28
+ self
29
+ end
30
+
31
+ def max_length(value)
32
+ options[:max_length] = Coercion.coerce!(value, Coercion::Integer)
33
+ self
34
+ end
35
+
21
36
  end
22
37
 
23
38
  end
@@ -3,11 +3,6 @@ module Compel
3
3
 
4
4
  module CommonValue
5
5
 
6
- def is(value)
7
- options[:is] = value
8
- self
9
- end
10
-
11
6
  def in(value)
12
7
  options[:in] = value
13
8
  self
@@ -14,10 +14,6 @@ module Compel
14
14
  self
15
15
  end
16
16
 
17
- def validate(object)
18
- Contract.new(object, self).validate
19
- end
20
-
21
17
  end
22
18
 
23
19
  end
@@ -11,6 +11,7 @@ require 'compel/builder/time'
11
11
  require 'compel/builder/date'
12
12
  require 'compel/builder/boolean'
13
13
  require 'compel/builder/array'
14
+ require 'compel/builder/any'
14
15
 
15
16
  module Compel
16
17
  module Builder
@@ -57,6 +58,10 @@ module Compel
57
58
  Builder::Array.new
58
59
  end
59
60
 
61
+ def any
62
+ Builder::Any.new
63
+ end
64
+
60
65
  extend self
61
66
 
62
67
  end
@@ -10,17 +10,7 @@ module Compel
10
10
  end
11
11
 
12
12
  def format(regex)
13
- options[:format] = Coercion.coerce!(regex, ::Regexp)
14
- self
15
- end
16
-
17
- def min_length(value)
18
- options[:min_length] = Coercion.coerce!(value, ::Integer)
19
- self
20
- end
21
-
22
- def max_length(value)
23
- options[:max_length] = Coercion.coerce!(value, ::Integer)
13
+ options[:format] = Coercion.coerce!(regex, Coercion::Regexp)
24
14
  self
25
15
  end
26
16
 
@@ -10,6 +10,7 @@ require 'compel/coercion/types/json'
10
10
  require 'compel/coercion/types/boolean'
11
11
  require 'compel/coercion/types/regexp'
12
12
  require 'compel/coercion/types/array'
13
+ require 'compel/coercion/types/any'
13
14
 
14
15
  require 'compel/coercion/result'
15
16
  require 'compel/coercion/nil_result'
@@ -18,10 +19,6 @@ module Compel
18
19
 
19
20
  module Coercion
20
21
 
21
- def valid?(value, type, options = {})
22
- coerce(value, type, options).valid?
23
- end
24
-
25
22
  def coerce!(value, type, options = {})
26
23
  result = coerce(value, type, options)
27
24
 
@@ -33,11 +30,9 @@ module Compel
33
30
  end
34
31
 
35
32
  def coerce(value, type, options = {})
36
- return NilResult.new if value.nil?
37
-
38
- coercion_klass = Compel::Coercion.const_get("#{type}")
33
+ return Coercion::NilResult.new if value.nil?
39
34
 
40
- coercion_klass.new(value, options).coerce
35
+ type.coerce(value, options)
41
36
  end
42
37
 
43
38
  extend self
@@ -0,0 +1,13 @@
1
+ module Compel
2
+ module Coercion
3
+
4
+ class Any < Type
5
+
6
+ def coerce_value
7
+ value
8
+ end
9
+
10
+ end
11
+
12
+ end
13
+ end
@@ -1,3 +1,5 @@
1
+ require 'json'
2
+
1
3
  module Compel
2
4
  module Coercion
3
5
 
@@ -6,6 +6,10 @@ module Compel
6
6
  attr_accessor :value,
7
7
  :options
8
8
 
9
+ def self.coerce(value, options)
10
+ new(value, options).coerce
11
+ end
12
+
9
13
  def initialize(value, options = {})
10
14
  @value = value
11
15
  @options = options
@@ -20,7 +24,7 @@ module Compel
20
24
  return result
21
25
  end
22
26
 
23
- Result.new(result, value, self.class)
27
+ Coercion::Result.new(result, value, self.class)
24
28
  end
25
29
 
26
30
  end
data/lib/compel/errors.rb CHANGED
@@ -7,7 +7,7 @@ module Compel
7
7
  end
8
8
 
9
9
  def add(key, error)
10
- if error.empty?
10
+ if error.nil? || error.empty?
11
11
  return
12
12
  end
13
13
 
@@ -0,0 +1,31 @@
1
+ module Compel
2
+ module Validation
3
+
4
+ class Condition
5
+
6
+ attr_reader :value,
7
+ :options,
8
+ :value_type,
9
+ :option_value
10
+
11
+ def self.validate(value, option_value, options = {})
12
+ new(value, option_value, options).validate
13
+ end
14
+
15
+ def initialize(value, option_value, options = {})
16
+ @value = value
17
+ @value_type = options.delete(:type) || Coercion::Types::Any
18
+ @option_value = option_value
19
+ end
20
+
21
+ def validate
22
+ # result is an error message
23
+ result = validate_value
24
+
25
+ Validation::Result.new(value, value_type, result)
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module Compel
2
+ module Validation
3
+
4
+ class Format < Condition
5
+
6
+ def validate_value
7
+ if value_type == Coercion::String && !valid?
8
+ "must match format #{option_value.source}"
9
+ end
10
+ end
11
+
12
+ def valid?
13
+ !value.nil? && value =~ option_value
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ module Compel
2
+ module Validation
3
+
4
+ class In < Condition
5
+
6
+ def validate_value
7
+ unless valid?
8
+ "must be within #{option_value}"
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def valid?
15
+ option_value.include?(value)
16
+ end
17
+
18
+ end
19
+
20
+ class Within < In; end
21
+
22
+ class Range < In; end
23
+
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ module Compel
2
+ module Validation
3
+
4
+ class Is < Condition
5
+
6
+ def option_value
7
+ if value_type == Coercion::Hash
8
+ return @option_value.to_hash
9
+ end
10
+
11
+ @option_value
12
+ end
13
+
14
+ def validate_value
15
+ unless valid?
16
+ "must be #{option_value}"
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def valid?
23
+ value == option_value
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ module Compel
2
+ module Validation
3
+
4
+ class Length < Condition
5
+
6
+ def validate_value
7
+ unless valid?
8
+ "cannot have length different than #{option_value}"
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def valid?
15
+ !value.nil? && option_value == "#{value}".length
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Compel
2
+ module Validation
3
+
4
+ class Max < Condition
5
+
6
+ def validate_value
7
+ unless valid?
8
+ "cannot be greater than #{option_value}"
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def valid?
15
+ !value.nil? && value <= option_value
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Compel
2
+ module Validation
3
+
4
+ class MaxLength < Condition
5
+
6
+ def validate_value
7
+ unless valid?
8
+ "cannot have length greater than #{option_value}"
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def valid?
15
+ !value.nil? && "#{value}".length <= option_value
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Compel
2
+ module Validation
3
+
4
+ class Min < Condition
5
+
6
+ def validate_value
7
+ unless valid?
8
+ "cannot be less than #{option_value}"
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def valid?
15
+ !value.nil? && value >= option_value
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Compel
2
+ module Validation
3
+
4
+ class MinLength < Condition
5
+
6
+ def validate_value
7
+ unless valid?
8
+ "cannot have length less than #{option_value}"
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def valid?
15
+ !value.nil? && option_value <= "#{value}".length
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ module Compel
2
+ module Validation
3
+
4
+ class Result
5
+
6
+ attr_reader :value,
7
+ :klass,
8
+ :error_message
9
+
10
+ def initialize(value, klass, error_message = nil)
11
+ @value = value
12
+ @klass = klass
13
+ @error_message = error_message
14
+ end
15
+
16
+ def valid?
17
+ @error_message.nil?
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end