compel 0.3.2 → 0.3.4

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.
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