validator_fn 0.1.6 → 0.2.8

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
  SHA256:
3
- metadata.gz: 9a18a2dee04cebf84a277132258a1456f981fe477467d041ea6c29e564051a74
4
- data.tar.gz: 2c82211054e4b07ee55f068dd87218b8f4d2da001889cd054d220be6346d84f0
3
+ metadata.gz: cecd9880750c518fcd26fd705b76ffeaf4604fb90af4bd60719ecf37a387d8ee
4
+ data.tar.gz: d04d0ef810ab4ac5ea7b8914690c1995ffdf913c8ad4a40c5bfa85ce5ce8a817
5
5
  SHA512:
6
- metadata.gz: d027d9af4b77d44e4b0dc9271faeb9bc89dc0e617439442f1858215ff06a8f806edac282379c1e28b176cc532522b3c5258aadc29c6745649930e2bfe6ac92ef
7
- data.tar.gz: 42385b0fbcdeb03906d81e4e4d32c29d6d19edcbb950586afc85553baba260823792e72e1f9f03fae5440e16d07160272996dacee50a2c971817dc8f68d0297e
6
+ metadata.gz: 52647b99fdac1ff9dcf399b96d4b5a5becac6748270795cb47f0caa11e1735217239108450418781bf933dabdc0accf3ef3eaf7c9b8feb9fc1bd5f3deabe34d9
7
+ data.tar.gz: 5c16a63c7a8f261cf8cf76af633dbc448975dd77cbe08074abf2dd8f77cca95b42baa3ce876c08d2f3186d52eee68edd1a94abea6b33440263e617364732d6a3
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- validator_fn (0.1.6)
4
+ validator_fn (0.1.8)
5
5
  fn_reader
6
6
 
7
7
  GEM
@@ -9,7 +9,7 @@ GEM
9
9
  specs:
10
10
  coderay (1.1.3)
11
11
  diff-lcs (1.4.4)
12
- fn_reader (0.1.0)
12
+ fn_reader (0.2.0)
13
13
  method_source (0.9.2)
14
14
  pry (0.12.2)
15
15
  coderay (~> 1.1.0)
data/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # ValidatorFn
2
2
 
3
- ValidatorFn is a collection of very simple lambdas that can be used for validating/transforming
4
- data structures. It makes use of currying in order to provide a very composable
5
- DSL. To help you understand the concepts it is stongly advised to read [this blog post.](http://blog.martinosis.com/blog/simple-functional-strong-params-in-ruby/).
3
+ ValidatorFn is a collection of very simple lambdas that can be used for validating/transforming
4
+ data structures. It makes use of currying to provide a very composable
5
+ DSL. To help you understand the concepts, I strongly advise reading [this blog post.](http://blog.martinosis.com/blog/simple-functional-strong-params-in-ruby/).
6
6
 
7
+ It can be very useful for validating structures that come from input, such as configuration files, JSON APIs, test results.
7
8
 
8
9
  ## Installation
9
10
 
@@ -23,30 +24,30 @@ Or install it yourself as:
23
24
 
24
25
  ## Usage
25
26
 
26
- ```
27
+ ```ruby
27
28
  require 'validator_fn'
28
29
  include ValidatorFn
29
30
  ```
30
31
 
31
- You can start validating type of an object.
32
+ You can start validating the type of an object.
32
33
 
33
- ```
34
+ ```ruby
34
35
  is_a.(String).(3)
35
36
  ```
36
37
 
37
- Note that parameters are curried. The first param of `is_a` is the Ruby class that you want to check the last parameter against.
38
- In the previous example, aValidatorFn::Error`exception will be raised.
38
+ Note that parameters are curried. The first param of `is_a` is the Ruby class you want to check the last parameter against.
39
+ In the previous example, a `ValidatorFn::Error`exception will be raised.
39
40
 
40
- However if you send a valid entry as the second parameter, it will return that last parameter.
41
+ However, setting a valid entry as the second parameter will return that last parameter.
41
42
 
42
- ```
43
+ ```ruby
43
44
  is_a.(String).("Joe")
44
45
  # => "Joe"
45
46
  ```
46
47
 
47
48
  This allows chaining lambdas:
48
49
 
49
- ```
50
+ ```ruby
50
51
  to_int = is_a.(String) >> -> a { Integer(a) }
51
52
 
52
53
  to_int.("12")
@@ -56,25 +57,91 @@ to_int.("asdf") # will raise an exception
56
57
 
57
58
  You can validate a hash:
58
59
 
59
- ```
60
+ ```ruby
60
61
  user = hash_of.({name: is_a.(String), age: to_int})
61
62
  user.({name: "", age: "234"})
62
63
  ```
63
64
 
64
- Since we are using curried lambdas, you can compose validators as you which.
65
+ Since we are using curried lambdas, you can compose validators as you which.
65
66
 
66
- ```
67
- postal_code = -> a {
67
+ ```ruby
68
+ postal_code = -> a {
68
69
  invalid.("Invalid postal code: #{a}") unless a =~ /[a-z]\d[a-z]\s*\d[a-z]\d/i
69
70
  a
70
71
  }
71
- contact = hash_of.(user: user,
72
- address: hash_of.({ street_number: is_a.(Integer),
72
+ contact = hash_of.(user: user,
73
+ address: hash_of.({ street_number: is_a.(Integer),
73
74
  postal_code: postal_code}))
74
75
  ```
75
76
 
76
- This is a very simple library (100 lines of code) that can be extended as you which by
77
- creating your own lambdas.
77
+ This very simple library (100 lines of code) can be extended easily by creating new lambdas.
78
+
79
+ ## Casting
80
+
81
+ You can also apply converter functions to the structure.
82
+
83
+ ```ruby
84
+ user = { name: "Joe", created_at: "2020-01-03" }
85
+ to_date = ->str { Date.parse(str) }
86
+ user_validator = hash_of.(name: is_a.(String),
87
+ created_at: is_a.(String) >> to_date)
88
+
89
+ user_validator.(user)
90
+ # => {:name=>"Joe", :created_at=>#<Date: 2020-01-03 ((2458852j,0s,0n),+0s,2299161j)>}
91
+ ```
92
+
93
+ This makes it very useful for processing JSON payloads.
94
+
95
+ ## Code generation
96
+
97
+ You can generate validator code from existing structure:
98
+
99
+ ```ruby
100
+ require 'openuri'
101
+ require "json"
102
+ struct = JSON.parse(URI.open("https://api.github.com/users/defunkt").read)
103
+
104
+ require "validator_fn"
105
+
106
+ # Generate unformatted code
107
+ code = ValidatorFn.generate_validator.(struct)
108
+
109
+ # You can reformat it using a code formatter
110
+ require "rufo"
111
+ puts Rufo.format(code)
112
+ hash_of.({ "login" => is_a.(String),
113
+ "id" => is_a.(Integer),
114
+ "node_id" => is_a.(String),
115
+ "avatar_url" => is_a.(String),
116
+ "gravatar_id" => is_a.(String),
117
+ "url" => is_a.(String),
118
+ "html_url" => is_a.(String),
119
+ "followers_url" => is_a.(String),
120
+ "following_url" => is_a.(String),
121
+ "gists_url" => is_a.(String),
122
+ "starred_url" => is_a.(String),
123
+ "subscriptions_url" => is_a.(String),
124
+ "organizations_url" => is_a.(String),
125
+ "repos_url" => is_a.(String),
126
+ "events_url" => is_a.(String),
127
+ "received_events_url" => is_a.(String),
128
+ "type" => is_a.(String),
129
+ "site_admin" => is_a_bool,
130
+ "name" => is_a.(String),
131
+ "company" => any,
132
+ "blog" => is_a.(String),
133
+ "location" => any,
134
+ "email" => any,
135
+ "hireable" => any,
136
+ "bio" => is_a.(String),
137
+ "twitter_username" => any,
138
+ "public_repos" => is_a.(Integer),
139
+ "public_gists" => is_a.(Integer),
140
+ "followers" => is_a.(Integer),
141
+ "following" => is_a.(Integer),
142
+ "created_at" => is_a.(String),
143
+ "updated_at" => is_a.(String) })
144
+ ```
78
145
 
79
146
  ## Development
80
147
 
@@ -86,7 +153,6 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
86
153
 
87
154
  Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/validator_fn. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/validator_fn/blob/master/CODE_OF_CONDUCT.md).
88
155
 
89
-
90
156
  ## License
91
157
 
92
158
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -94,6 +160,3 @@ The gem is available as open source under the terms of the [MIT License](https:/
94
160
  ## Code of Conduct
95
161
 
96
162
  Everyone interacting in the ValidatorFn project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/validator_fn/blob/master/CODE_OF_CONDUCT.md).
97
- Everyone interacting in the ValidatorFn project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/validator_fn/blob/master/CODE_OF_CONDUCT.md).
98
- Everyone interacting in the ValidatorFn project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/validator_fn/blob/master/CODE_OF_CONDUCT.md).
99
- Everyone interacting in the ValidatorFn project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/validator_fn/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,29 @@
1
+ module ValidatorFn
2
+ class Error < StandardError
3
+ attr_reader :my_msg
4
+
5
+ def initialize(msg)
6
+ @my_msg = msg
7
+ super(msg)
8
+ end
9
+
10
+ def message(indent = 0)
11
+ if cause
12
+ cause_msg = if cause.kind_of?(Error)
13
+ cause.message(indent + 1)
14
+ else
15
+ cause.message
16
+ end
17
+ my_msg + "\n" + (" " * (indent + 1)) + cause_msg
18
+ else
19
+ my_msg
20
+ end
21
+ end
22
+ end
23
+
24
+ class MissingKey < Error
25
+ def initialize(key)
26
+ super("Missing field #{key}")
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module ValidatorFn
2
- VERSION = "0.1.6"
2
+ VERSION = "0.2.8"
3
3
  end
data/lib/validator_fn.rb CHANGED
@@ -1,33 +1,10 @@
1
1
  require "validator_fn/version"
2
+ require "validator_fn/error"
2
3
  require "fn_reader"
3
4
 
4
5
  module ValidatorFn
5
- class Error < StandardError; end
6
-
7
6
  fn_reader :something, :matches, :either, :array_of, :any, :is_nil,
8
- :maybe, :present, :is_a, :int, :hash_of, :invalid, :generate_validator, :handle_error, :error_str, :apply
9
-
10
- class Error < StandardError
11
- attr_reader :my_msg
12
-
13
- def initialize(msg)
14
- @my_msg = msg
15
- super(msg)
16
- end
17
-
18
- def message(indent = 0)
19
- if cause
20
- cause_msg = if cause.kind_of?(Error)
21
- cause.message(indent + 1)
22
- else
23
- cause.message
24
- end
25
- my_msg + "\n" + (" " * (indent + 1)) + cause_msg
26
- else
27
- my_msg
28
- end
29
- end
30
- end
7
+ :maybe, :present, :is_a, :is_a_bool, :int, :hash_of, :invalid, :generate_validator, :handle_error, :error_str, :apply
31
8
 
32
9
  @@apply = ->fn, a {
33
10
  begin
@@ -59,11 +36,19 @@ module ValidatorFn
59
36
  @@is_nil = ->a { invalid.("Should be nil but was #{a}") unless a.nil?; a }
60
37
  @@maybe = either.(is_nil)
61
38
  @@is_a = ->klass, a { invalid.("Expected type #{klass}, got #{a.inspect}") unless a.is_a?(klass); a }.curry
39
+ @@is_a_bool = ->a { invalid.("Expected bool, got #{a.inspect}") unless a == true || a == false; a }.curry
62
40
  @@hash_of = ->fields, hash {
63
41
  hash ||= {}
64
42
  fields.reduce({}) do |memo, (key, fn)|
65
- memo[key] ||= fn.(hash[key]) if hash[key]
43
+ value = hash.fetch(key, :missing_field)
44
+ if value == :missing_field
45
+ raise MissingKey.new(key)
46
+ else
47
+ memo[key] = fn.(hash[key]) if hash[key]
48
+ end
66
49
  memo
50
+ rescue MissingKey => e
51
+ raise
67
52
  rescue Error => e
68
53
  invalid.("Invalid value for #{key.inspect} key.")
69
54
  end
@@ -97,6 +82,10 @@ module ValidatorFn
97
82
  "hash_of.({ #{inner} })"
98
83
  when Array
99
84
  "array_of.( #{generate_validator.(a.first)} )"
85
+ when TrueClass
86
+ "is_a_bool"
87
+ when FalseClass
88
+ "is_a_bool"
100
89
  else
101
90
  "is_a.(#{a.class})"
102
91
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: validator_fn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Chabot
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-12 00:00:00.000000000 Z
11
+ date: 2022-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fn_reader
@@ -43,6 +43,7 @@ files:
43
43
  - bin/console
44
44
  - bin/setup
45
45
  - lib/validator_fn.rb
46
+ - lib/validator_fn/error.rb
46
47
  - lib/validator_fn/version.rb
47
48
  - validator_fn.gemspec
48
49
  homepage: https://github.com/martinos/validator_fn
@@ -66,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
67
  - !ruby/object:Gem::Version
67
68
  version: '0'
68
69
  requirements: []
69
- rubygems_version: 3.1.4
70
+ rubygems_version: 3.1.2
70
71
  signing_key:
71
72
  specification_version: 4
72
73
  summary: Series of lambdas for validating Ruby structures