broi-input 0.1.1 → 0.1.2

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: e1d4bf01c2fc021ccffa526f54dbffdcb6c08670e70a85727293265a38d47d33
4
- data.tar.gz: 11ff7e9d518d43152c5a8a8c6bf02ffa6737dd666d77d94c5d667ca4b27a7d50
3
+ metadata.gz: 9ec70915468a81f1e76fd79fa968c819a708c8d65040b2feee9da121f6f21458
4
+ data.tar.gz: 1ba022fe06b37bac5d8d59aa263420cd5069cc481a215c43dbb58c5b2e665093
5
5
  SHA512:
6
- metadata.gz: 6de0dbefbe0fc3620826d4d84b5fdd70363c0794621701596a1962f475fdbd2cead1cba392e546cb9f7fe86bb34339ec77210ce7559f0eb615022d9352fdc72d
7
- data.tar.gz: 51b957814dfdda10fef8beb2291f4d8527a6d606c7158396bb90b99c3b45c43ddb1c37443b5f5cdc651f589bdbd563b1c42eb403a7c04ce52969fe878de8a5e4
6
+ metadata.gz: 35b14bb7ffa1339d748fb21cc66bb545ff231dde3f78798282199adfc72f192af22cba0e86e9780750948ebc0129f83805bd54a52918596097bd041fb943d603
7
+ data.tar.gz: 781d9b48dc23b59c32cf24ed7c174e3c04c2dca8de0edaafeada7321e244776cc5a32ddf668888a5a6540518f796362f02adc4eec3d8bd5977c6aaa3a0d96181
data/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /*.gem
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- broi-input (0.1.0)
4
+ broi-input (0.1.1)
5
+ dry-monads (~> 1.0)
5
6
  dry-struct (~> 0.5)
6
- dry-transaction (~> 0.13)
7
7
  dry-validation (~> 0.12)
8
8
 
9
9
  GEM
@@ -21,16 +21,11 @@ GEM
21
21
  dry-core (0.4.7)
22
22
  concurrent-ruby (~> 1.0)
23
23
  dry-equalizer (0.2.1)
24
- dry-events (0.1.0)
25
- concurrent-ruby (~> 1.0)
26
- dry-core (~> 0.4)
27
- dry-equalizer (~> 0.2)
28
24
  dry-inflector (0.1.2)
29
25
  dry-logic (0.4.2)
30
26
  dry-container (~> 0.2, >= 0.2.6)
31
27
  dry-core (~> 0.2)
32
28
  dry-equalizer (~> 0.2)
33
- dry-matcher (0.7.0)
34
29
  dry-monads (1.0.0)
35
30
  concurrent-ruby (~> 1.0)
36
31
  dry-core (~> 0.4, >= 0.4.4)
@@ -40,11 +35,6 @@ GEM
40
35
  dry-equalizer (~> 0.2)
41
36
  dry-types (~> 0.13)
42
37
  ice_nine (~> 0.11)
43
- dry-transaction (0.13.0)
44
- dry-container (>= 0.2.8)
45
- dry-events (>= 0.1.0)
46
- dry-matcher (>= 0.7.0)
47
- dry-monads (>= 0.4.0)
48
38
  dry-types (0.13.2)
49
39
  concurrent-ruby (~> 1.0)
50
40
  dry-container (~> 0.3)
@@ -52,7 +42,7 @@ GEM
52
42
  dry-equalizer (~> 0.2)
53
43
  dry-inflector (~> 0.1, >= 0.1.2)
54
44
  dry-logic (~> 0.4, >= 0.4.2)
55
- dry-validation (0.12.0)
45
+ dry-validation (0.12.1)
56
46
  concurrent-ruby (~> 1.0)
57
47
  dry-configurable (~> 0.1, >= 0.1.3)
58
48
  dry-core (~> 0.2, >= 0.2.1)
data/README.md CHANGED
@@ -1,43 +1,70 @@
1
- # Input
1
+ # Broi::Input
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/input`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ This library provides flexible API to deal with incoming ruby messages. It converts incoming hash onto predefined, structured object by passing it through predefined input validations.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ Example:
6
6
 
7
- ## Installation
7
+ ```ruby
8
+ class PurchaseInput < Broi::Input
9
+ attribute :product
10
+ attribute :count, default: 1
11
+
12
+ validate do
13
+ required(:product).filled(:str?)
14
+ optional(:count).maybe(:int?)
15
+ end
16
+ end
17
+ ```
18
+
19
+ ###Processing incoming hash
8
20
 
9
- Add this line to your application's Gemfile:
21
+ You instantiate the input by executing `call` method which, depending on the validation resutls, returns an instance of Broi::Input::Success/Failure.
10
22
 
11
23
  ```ruby
12
- gem 'input'
24
+ PurchaseInput.(product: 'Apple')
25
+ #=> #Success(<#PurchaseInput|soft product=#Value('Apple')>)
26
+
27
+
28
+ PurchaseInput.(product: 123)
29
+ #=> Failure({:product => ["must be string"])
13
30
  ```
14
31
 
15
- And then execute:
32
+ ### Soft input struct
16
33
 
17
- $ bundle
34
+ Regardless of the validation result, you can always obtain soft input result by calling `input` on the result:
18
35
 
19
- Or install it yourself as:
36
+ ```ruby
37
+ PurchaseInput.(product: 'Apple').input
38
+ #=> <#PurchaseInput|soft product=#Value('Apple')>
20
39
 
21
- $ gem install input
40
+ PurchaseInput.(product: 123).input
41
+ #=> <#PurchaseInput|soft product=#InvalidValue(123)>
42
+ ```
22
43
 
23
- ## Usage
44
+ All the values accessible through the soft input are either `Broi::Input::Value`/`InvalidValue` and they respond to `valid?` and `invalid?` methods.
24
45
 
25
- TODO: Write usage instructions here
46
+ ### Strict input
26
47
 
27
- ## Development
48
+ You can turn soft input into a strict input by calling `valid!`. Strict input is just typical Dry::Struct:
28
49
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
50
+ ```ruby
51
+ PurchaseInput.(product: 'Apple').input.valid!
52
+ #=> <#PurchaseInput product='Apple'>
30
53
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
54
+ PurchaseInput.(product: 123).input.valid!
55
+ #! raises: Broi::Input::Invalid
56
+ ```
32
57
 
33
- ## Contributing
58
+ ### Validation errors
34
59
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/input. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
60
+ Errors can be collected directly from the processing result.
36
61
 
37
- ## License
62
+ ```ruby
63
+ PurchaseInput.(product: 'Apple').errors
64
+ #=> {}
38
65
 
39
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
66
+ PurchaseInput.(product: 123).errors
67
+ #=> {:product => ["must be string"])
68
+ ```
40
69
 
41
- ## Code of Conduct
42
70
 
43
- Everyone interacting in the Input project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/input/blob/master/CODE_OF_CONDUCT.md).
data/input.gemspec CHANGED
@@ -4,17 +4,18 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'broi-input'
7
- spec.version = '0.1.1'
7
+ spec.version = '0.1.2'
8
8
  spec.authors = ['broisatse']
9
9
  spec.email = ['sklajn@gmail.com']
10
10
 
11
11
  spec.summary = 'Simple ruby object to handle user inputs'
12
- spec.description = %q{Destructure incoming user input onto dry struct}
12
+ spec.description = 'Destructures incoming user input onto dry struct'
13
13
  spec.homepage = 'https://github.com/BroiSatse/broi-input'
14
14
  spec.license = 'MIT'
15
15
 
16
16
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
17
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ `git ls-files -z`.split("\x0")
18
+ .reject { |f| f.match(%r{^(test|spec|features)/}) }
18
19
  end
19
20
  spec.bindir = 'exe'
20
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -22,10 +23,12 @@ Gem::Specification.new do |spec|
22
23
 
23
24
  spec.add_dependency 'dry-validation', '~> 0.12'
24
25
  spec.add_dependency 'dry-struct', '~> 0.5'
26
+ spec.add_dependency 'dry-monads', '~> 1.0'
25
27
 
26
28
 
27
29
  spec.add_development_dependency 'bundler', '~> 1.16'
28
30
  spec.add_development_dependency 'rake', '~> 10.0'
29
31
  spec.add_development_dependency 'rspec', '~> 3.0'
30
32
  spec.add_development_dependency 'pry', '~> 0.11'
33
+ spec.add_development_dependency 'byebug'
31
34
  end
@@ -0,0 +1,16 @@
1
+ module Broi
2
+ class Input < Dry::Struct::Value
3
+ class Failure < Dry::Monads::Failure
4
+ def initialize(input, errors)
5
+ @input = input
6
+ super(errors)
7
+ end
8
+
9
+ attr_reader :input
10
+
11
+ def errors
12
+ failure
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ module Broi
2
+ class Input < Dry::Struct::Value
3
+ Invalid = Class.new(StandardError)
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ module Broi
2
+ class Input < Dry::Struct::Value
3
+ class InvalidValue < Dry::Monads::Failure
4
+ def inspect
5
+ "#InvalidValue(#{failure.inspect})"
6
+ end
7
+
8
+ def valid?
9
+ false
10
+ end
11
+
12
+ def invalid?
13
+ true
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,54 @@
1
+ require 'broi/input/invalid_error'
2
+
3
+ module Broi
4
+ class Input < Dry::Struct::Value
5
+ module SoftInput
6
+ def self.included(mod)
7
+ mod.extend ClassMethods
8
+ end
9
+
10
+ def valid!
11
+ self.class.superclass.new Utils.deep_transform_values(attributes, &:value!)
12
+ rescue Dry::Monads::UnwrapError
13
+ raise Invalid, 'Called `valid!` on invalid soft input!'
14
+ end
15
+
16
+ def strict?
17
+ false
18
+ end
19
+
20
+ module ClassMethods
21
+ def inspect
22
+ "#{superclass.name}|soft"
23
+ end
24
+ end
25
+ end
26
+
27
+ module Soft
28
+ class << self
29
+ def [](klass)
30
+ register[klass]
31
+ end
32
+
33
+ private
34
+
35
+ def register
36
+ @register ||= Hash.new do |hash, klass|
37
+ hash[klass] = Class.new(klass).include(SoftInput)
38
+ end
39
+ end
40
+ end
41
+
42
+ def self.call(input_class, attrs, errors)
43
+ attrs = input_class.input[attrs]
44
+ input = Utils.deep_merge(attrs, errors) do |target, _error|
45
+ InvalidValue.new(target)
46
+ end
47
+ input = Utils.deep_transform_values(input) do |value|
48
+ value.is_a?(InvalidValue) ? value : Value.new(value)
49
+ end
50
+ self[input_class].new(input)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,13 @@
1
+ module Broi
2
+ class Input < Dry::Struct::Value
3
+ class Success < Dry::Monads::Success
4
+ def input
5
+ value!
6
+ end
7
+
8
+ def errors
9
+ {}
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ module Broi
2
+ class Input < Dry::Struct::Value
3
+ module Utils
4
+ extend self
5
+
6
+ def deep_transform_values(object, &block)
7
+ if object.is_a?(Hash)
8
+ object.transform_values { |value| deep_transform_values(value, &block) }
9
+ else
10
+ block.(object)
11
+ end
12
+ end
13
+
14
+ def deep_merge(target, source, &block)
15
+ if target.is_a?(Hash) && source.is_a?(Hash)
16
+ keys = (target.keys + source.keys).uniq
17
+ keys.map do |key|
18
+ value = if [target, source].all? { |h| h.key? key }
19
+ deep_merge(target[key], source[key], &block)
20
+ else
21
+ [target[key], source[key]].compact.first
22
+ end
23
+ [key, value]
24
+ end.to_h
25
+ else
26
+ block ||= ->(_target, source) { source }
27
+ block.(target, source)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ module Broi
2
+ class Input < Dry::Struct::Value
3
+ class Value < Dry::Monads::Success
4
+ def inspect
5
+ "#Value(#{value!.inspect})"
6
+ end
7
+
8
+ def valid?
9
+ true
10
+ end
11
+
12
+ def invalid?
13
+ false
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/broi/input.rb CHANGED
@@ -1,10 +1,18 @@
1
1
  require 'dry-struct'
2
- require 'dry/transaction'
3
2
  require 'dry/validation'
3
+ require 'dry/monads/result'
4
+
5
+ require 'broi/input/success'
6
+ require 'broi/input/failure'
7
+ require 'broi/input/utils'
8
+ require 'broi/input/value'
9
+ require 'broi/input/invalid_value'
10
+ require 'broi/input/soft'
11
+
12
+ require 'byebug'
4
13
 
5
14
  module Broi
6
15
  class Input < Dry::Struct::Value
7
- # include Dry::Transaction
8
16
 
9
17
  module Types
10
18
  include Dry::Types.module
@@ -12,10 +20,14 @@ module Broi
12
20
 
13
21
  transform_keys(&:to_sym)
14
22
 
23
+ def strict?
24
+ true
25
+ end
26
+
15
27
  class << self
16
- def attribute(name, type = nil, **opts, &block)
17
- type ||= Types::Any
18
- type = type.optional.meta(omittable: true)
28
+
29
+ def attribute(name, **opts, &block)
30
+ type = Types::Any.optional.meta(omittable: true)
19
31
  type = type.default(opts[:default]) if opts.has_key?(:default)
20
32
  super(name, type, &block)
21
33
  end
@@ -30,10 +42,29 @@ module Broi
30
42
 
31
43
  def call(params = {})
32
44
  result = validation.(params)
45
+ input = Soft.(self, result.output, result.errors)
46
+ # output = input[result.output]
47
+ # input = Utils.deep_merge(output, result.errors) do |target, _error|
48
+ # InvalidValue.new(target)
49
+ # end
50
+ # input = Utils.deep_transform_values(input) do |value|
51
+ # value.is_a?(InvalidValue) ? value : Value.new(value)
52
+ # end
53
+ # input = new(input)
33
54
  if result.success?
34
- Dry::Monads::Success.new new(result.output)
55
+ Success.new(input)
56
+ else
57
+ Failure.new(input, result.errors)
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def merge_error(input_value, error)
64
+ if input_value.is_a? Hash
65
+
35
66
  else
36
- Dry::Monads::Failure.new result.errors
67
+ error ? InvalidValue.new : input_value
37
68
  end
38
69
  end
39
70
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: broi-input
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - broisatse
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-07-03 00:00:00.000000000 Z
11
+ date: 2018-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-validation
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: dry-monads
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -94,7 +108,21 @@ dependencies:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0.11'
97
- description: Destructure incoming user input onto dry struct
111
+ - !ruby/object:Gem::Dependency
112
+ name: byebug
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Destructures incoming user input onto dry struct
98
126
  email:
99
127
  - sklajn@gmail.com
100
128
  executables: []
@@ -114,6 +142,13 @@ files:
114
142
  - bin/setup
115
143
  - input.gemspec
116
144
  - lib/broi/input.rb
145
+ - lib/broi/input/failure.rb
146
+ - lib/broi/input/invalid_error.rb
147
+ - lib/broi/input/invalid_value.rb
148
+ - lib/broi/input/soft.rb
149
+ - lib/broi/input/success.rb
150
+ - lib/broi/input/utils.rb
151
+ - lib/broi/input/value.rb
117
152
  homepage: https://github.com/BroiSatse/broi-input
118
153
  licenses:
119
154
  - MIT