validator_fn 0.1.7 → 0.3.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: f3c19ca1d1f502bed0157cfafa1f2a1b895ada518a58770f22f7ea3eeb159fb8
4
- data.tar.gz: e7d7cb6dd656953bded2541458316019a1578913907b473499520f86b59fda8a
3
+ metadata.gz: 6ea7512cdc3b010b687c5cf9d2fec7d79f6724c56547e31ced2903762e81e9b3
4
+ data.tar.gz: 5e45c2d9df2ff27104da89d0a97f19788a3de304b4575a3a317fa567620a6692
5
5
  SHA512:
6
- metadata.gz: c03edea5b8e2fecf7fb892ca22a4157ebfbe0dd8e717578cc5d38e3280c99ada72e72a18b6ee7c661e1d533261560037c47ff6c18065c28af7eb5478fc5c9f4e
7
- data.tar.gz: 382a11b7ea12ebda356c03039b3e5b2228d1dcc0d7e38ac95da7419f36b69ab932f14054fb44029cf6dfed670a6257f6bb270d2cd5abae98be54e004badc6af7
6
+ metadata.gz: e683c7186d468ac169210bab0a8033601b7873051381ee14f24dc1760d30f9dd8731723b303b8090464081afea842f8db309c8f5fc2d0666a54500efb31fd22d
7
+ data.tar.gz: f172ff2aa6e4b1f243ae50000da20f8a6cd86c385f872cbe0c2cea6f222e2c1b025ead98c1af6191637467646e1c11c42628bb9205546dc5a5ac8042b3f3b6ee
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.2.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.7"
2
+ VERSION = "0.3.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,13 +36,14 @@ 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
+ memo[key] = fn.(hash[key])
66
44
  memo
67
45
  rescue Error => e
68
- invalid.("Invalid value for #{key.inspect} key.")
46
+ invalid.("Invalid value for #{key.inspect} key:")
69
47
  end
70
48
  }.curry
71
49
 
@@ -97,6 +75,10 @@ module ValidatorFn
97
75
  "hash_of.({ #{inner} })"
98
76
  when Array
99
77
  "array_of.( #{generate_validator.(a.first)} )"
78
+ when TrueClass
79
+ "is_a_bool"
80
+ when FalseClass
81
+ "is_a_bool"
100
82
  else
101
83
  "is_a.(#{a.class})"
102
84
  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.7
4
+ version: 0.3.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-30 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