strum 0.0.56 → 0.1.0

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: ce5316836aff5a84ce5be1cb3af9445b5ebc80ba3c739626483929bb9ff7538d
4
- data.tar.gz: ed3b056c7ab24e67efd4cae7e0ac5ddd31f981099c6911b9e11b659bd42af315
3
+ metadata.gz: e42ae1ed242ca62b4424ebeb549eaccbd54f3b66348fb31bc7d65f457efdf1a0
4
+ data.tar.gz: a86f1a2c6d32b9c211b68702514411da590801ecbc6637b40a5a88f9d47f6699
5
5
  SHA512:
6
- metadata.gz: 622ed6bc448d6f0124b09d159ae9801478a8ef526cbb56ec4f948647f38ea7fc54df863722e5512e0e2b2391db07239dd7ef93d282f994ecf8e7cc3acfe28dc9
7
- data.tar.gz: db63d55f2a5ec36480e02f5dacf922f252f1a504a64af59c68fda4f500460436cc325702642a983c29e375d72a859c2b3aad1879edbf82257e2adf72a5a16586
6
+ metadata.gz: dfa1308d4b365e7ab7a0d945dadcc0289908e8e17760d2cde18741a3206ebd618d4d300250f92158825906a0c472866474084c24151da7e12baad9b670b3448f
7
+ data.tar.gz: 64482d3661a03579d1944723969d74e7b2f4c582e0e3386eb05391ab6796c6740e5acf8c95452c156fe2d05c5cdf8ac604a84261623166a5697a4b8c2e591bec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- strum (0.0.56)
4
+ strum (0.1.0)
5
5
  dry-inflector (~> 0.2.0)
6
6
  dry-struct (~> 1.2)
7
7
  json-schema (~> 2.8.1)
@@ -16,7 +16,7 @@ GEM
16
16
  ast (2.4.0)
17
17
  concurrent-ruby (1.1.6)
18
18
  diff-lcs (1.3)
19
- dry-configurable (0.11.3)
19
+ dry-configurable (0.11.5)
20
20
  concurrent-ruby (~> 1.0)
21
21
  dry-core (~> 0.4, >= 0.4.7)
22
22
  dry-equalizer (~> 0.2)
@@ -36,7 +36,7 @@ GEM
36
36
  dry-equalizer (~> 0.3)
37
37
  dry-types (~> 1.3)
38
38
  ice_nine (~> 0.11)
39
- dry-types (1.3.1)
39
+ dry-types (1.4.0)
40
40
  concurrent-ruby (~> 1.0)
41
41
  dry-container (~> 0.3)
42
42
  dry-core (~> 0.4, >= 0.4.4)
@@ -51,7 +51,7 @@ GEM
51
51
  json-schema (2.8.1)
52
52
  addressable (>= 2.4)
53
53
  parallel (1.19.1)
54
- parser (2.7.0.3)
54
+ parser (2.7.0.5)
55
55
  ast (~> 2.4.0)
56
56
  public_suffix (4.0.3)
57
57
  rainbow (3.0.0)
@@ -64,7 +64,7 @@ GEM
64
64
  rspec-mocks (~> 3.9.0)
65
65
  rspec-core (3.9.1)
66
66
  rspec-support (~> 3.9.1)
67
- rspec-expectations (3.9.0)
67
+ rspec-expectations (3.9.1)
68
68
  diff-lcs (>= 1.2.0, < 2.0)
69
69
  rspec-support (~> 3.9.0)
70
70
  rspec-mocks (3.9.1)
@@ -79,7 +79,7 @@ GEM
79
79
  ruby-progressbar (~> 1.7)
80
80
  unicode-display_width (>= 1.4.0, < 1.7)
81
81
  ruby-progressbar (1.10.1)
82
- sequel (5.29.0)
82
+ sequel (5.30.0)
83
83
  sequel-annotate (1.4.0)
84
84
  sequel (>= 4)
85
85
  thor (0.20.3)
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "strum"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
@@ -2,10 +2,10 @@
2
2
 
3
3
  require "strum/version"
4
4
  require "strum/service"
5
- require "strum/chain"
6
5
  require "strum/pipe"
7
6
  require "strum/json"
8
7
  require "strum/deep_keys_to_sym"
8
+ require "strum/json_schema"
9
9
 
10
10
  module Strum
11
11
  class Error < StandardError; end
@@ -0,0 +1,102 @@
1
+ require "strum/service"
2
+ require "json-schema"
3
+
4
+ module Strum
5
+ module JsonSchema
6
+ class Validate
7
+ include Strum::Service
8
+
9
+ def call
10
+ array_errors = JSON::Validator.fully_validate(args[:schema], input, errors_as_objects: true)
11
+ array_errors.each { |error| add_error(*self.parse_json_schema_error(error)) }
12
+ output(input)
13
+ end
14
+
15
+ def audit
16
+ add_error(:schema, :not_found) if !args[:schema].is_a?(Hash)
17
+ end
18
+
19
+ protected
20
+
21
+ def parse_json_schema_error(error)
22
+ id = error[:fragment].sub(/#/, "input")
23
+ keys = id.split("/")
24
+ last_key_idx = keys.rindex { |key| key !~ /[0-9]+/ }
25
+ last_key = keys.map { |key| key =~ /[0-9]+/ ? "[#{key}]" : ".#{key}" }.join[1..-1]
26
+ value = error[:message][0, error[:message].index(/ in schema/)].sub(error[:fragment], last_key)
27
+ [last_key.to_sym, value]
28
+ end
29
+ end
30
+
31
+ class Cast
32
+ include Strum::Service
33
+
34
+ def call
35
+ output(casted(input, args[:schema]))
36
+ end
37
+
38
+ def audit
39
+ add_error(:schema, :not_found) if !args[:schema].is_a?(Hash)
40
+ end
41
+
42
+ protected
43
+
44
+ def casted(input_data, schema)
45
+ @input_data = input_data
46
+
47
+ def rec_casted(schema, path = [])
48
+ item = self.custom_dig(@input_data, path)
49
+
50
+ if item.is_a?(NoValue)
51
+ return item
52
+ end
53
+
54
+ case schema[:type]
55
+ when Array
56
+ schema[:type].reduce(nil) do |type, x|
57
+ new_schema = schema.clone
58
+ new_schema[:type] = x
59
+ type ||= rec_casted(new_schema, path)
60
+ end
61
+ when "object"
62
+ if item.is_a?(Hash) && schema[:properties].is_a?(Hash)
63
+ schema[:properties].map { |key, val| [key, rec_casted(val, path + [key])] }.filter { |pair| !pair[1].is_a?(NoValue) }.to_h
64
+ end
65
+ when "array"
66
+ if item.is_a?(Array) && schema[:items].is_a?(Hash)
67
+ (0..(item.length - 1)).reduce([]) { |res, idx| res << rec_casted(schema[:items], path + [idx]) }
68
+ end
69
+ when "string"
70
+ item.to_s
71
+ when "integer"
72
+ if item.is_a?(Numeric)
73
+ item
74
+ elsif item.is_a?(String) || item.is_a?(Symbol)
75
+ item.to_s.to_i
76
+ end
77
+ when "boolean"
78
+ item.to_s.downcase == "true"
79
+ when "jsonb"
80
+ if (Module.constants.include?(:Sequel)) && (Sequel.methods.include?(:pg_jsonb_wrap))
81
+ Sequel.pg_jsonb_wrap(item)
82
+ else
83
+ add_error(:schema, "jsonb type is not supported")
84
+ end
85
+ when nil, ""
86
+ item
87
+ else
88
+ add_error(:schema, :invalid_type)
89
+ end
90
+ end
91
+
92
+ rec_casted(schema)
93
+ end
94
+
95
+ def custom_dig(obj, path)
96
+ path.reduce(obj) { |item, x| item.fetch(x) { |it| return NoValue.new } }
97
+ end
98
+ end
99
+
100
+ class NoValue; end
101
+ end
102
+ end
@@ -4,13 +4,13 @@ module Strum
4
4
  class Pipe
5
5
  include Strum::Service
6
6
 
7
- def self.call(*units, input: {}, unit_input: {}, &block)
7
+ def self.call(*units, args: {}, input: {}, unit_input: {}, &block)
8
8
  pipe_payload = if input.is_a?(Hash) && unit_input.is_a?(Hash)
9
9
  unit_input.merge(input)
10
10
  else
11
11
  input
12
12
  end
13
- new(pipe_payload).execute(*units, input, unit_input, &block)
13
+ new(pipe_payload, args).execute(*units, input, unit_input, &block)
14
14
  end
15
15
 
16
16
  def execute(*units, pipe_inputs, pipe_unit_inputs, &block)
@@ -24,6 +24,15 @@ module Strum
24
24
  raise Strum::Error, "Unit options must be a Hash" unless service_params.is_a?(Hash)
25
25
 
26
26
  service_options = service_params[:input] || {}
27
+ result_place = service_params[:to]
28
+ unit_args = case service_params[:args]
29
+ when Hash
30
+ service_params[:args]
31
+ when Symbol, String
32
+ { service_params[:args] => service_params[:args] }
33
+ else
34
+ {}
35
+ end
27
36
  clean_output = service_params[:clean_output] || false
28
37
  unit_payload = if !clean_output && service_options.is_a?(Hash) && pipe_unit_inputs.is_a?(Hash) && output_value.is_a?(Hash)
29
38
  pipe_unit_inputs.merge(service_options).merge(output_value)
@@ -31,21 +40,21 @@ module Strum
31
40
  output_value
32
41
  end
33
42
 
34
- service.public_send(:call, unit_payload) do |m|
35
- service_handlers[:on].each do |k, _handler|
36
- m.on(k) { |r| hook(k, r) }
43
+ service.public_send(:call, unit_payload, args.merge(unit_args)) do |m|
44
+ service_handlers[:on].each do |key, _handler|
45
+ m.on(key) { |r| hook(k, r) }
37
46
  end
38
47
 
39
- service_handlers[:success].each do |k, _handler|
40
- if k
41
- m.success(k) do |result|
42
- output(k, result)
48
+ service_handlers[:success].each do |key, _handler|
49
+ if key
50
+ m.success(key) do |result|
51
+ output(key, result)
43
52
  continue = false
44
53
  end
45
54
  else
46
55
  m.success do |result|
47
- if result.nil?
48
- # do nothing if service hasn't result
56
+ if result_place
57
+ inputs[result_place] = result
49
58
  elsif !clean_output && result.is_a?(Hash) && output_value.is_a?(Hash)
50
59
  output(output_value.merge(result))
51
60
  else
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require "json-schema"
3
2
 
4
3
  module Strum
5
4
  # Module
@@ -14,19 +13,18 @@ module Strum
14
13
 
15
14
  # Internal: Interactor class methods.
16
15
  module ClassMethods
17
- def call(_input = nil, &block)
18
- new(_input).execute(&block)
16
+ def call(_input, **args, &block)
17
+ new(_input, args).execute(&block)
19
18
  end
20
19
  end
21
20
 
22
21
  # Instance methods
23
- def initialize(_input)
22
+ def initialize(_input, **args)
24
23
  self.strum_errors = {}
25
24
  self.service_handlers = { on: {}, success: {}, failure: {} }
26
25
  self.outputs = {}
27
- self._input = _input
28
- self._input.freeze
29
- self.input = self._input.dup
26
+ self.inputs = args.merge(default: _input)
27
+ self._inputs = inputs.dup.freeze
30
28
  end
31
29
 
32
30
  def execute
@@ -72,7 +70,7 @@ module Strum
72
70
 
73
71
  protected
74
72
 
75
- attr_accessor :_input, :input, :strum_errors, :outputs, :service_handlers
73
+ attr_accessor :inputs, :_inputs, :strum_errors, :outputs, :service_handlers
76
74
 
77
75
  def call
78
76
  raise Failure, "call method must be implemented"
@@ -80,6 +78,22 @@ module Strum
80
78
 
81
79
  def audit; end
82
80
 
81
+ def input
82
+ inputs[:default]
83
+ end
84
+
85
+ def input=(value)
86
+ inputs[:default] = value
87
+ end
88
+
89
+ def _input
90
+ _inputs[:default]
91
+ end
92
+
93
+ def args
94
+ inputs.slice(*inputs.keys - [:default])
95
+ end
96
+
83
97
  def output_value(key = :default)
84
98
  @outputs[key]
85
99
  end
@@ -122,7 +136,7 @@ module Strum
122
136
 
123
137
  def sliced(*keys)
124
138
  if input.is_a?(Hash)
125
- @input = input.slice(*keys)
139
+ self.input = input.slice(*keys)
126
140
  else
127
141
  add_error(:input, :must_be_hash)
128
142
  end
@@ -130,7 +144,7 @@ module Strum
130
144
 
131
145
  def sliced_list(*keys)
132
146
  if input.is_a?(Array)
133
- @input = input.map do |item|
147
+ self.input = input.map do |item|
134
148
  if item.is_a?(Hash)
135
149
  item = item.slice(*keys)
136
150
  else
@@ -142,19 +156,6 @@ module Strum
142
156
  end
143
157
  end
144
158
 
145
- def validated(schema:, list: false)
146
- array_errors = JSON::Validator.fully_validate(schema, @input, errors_as_objects: true, list: list)
147
- array_errors.each{|error| add_error(*self.parse_json_schema_error(error))}
148
- end
149
-
150
- def parse_json_schema_error(error)
151
- pos_match = error[:fragment].match(/([0-9]+)[\/]?/)
152
- pos = pos_match.is_a?(Array) ? pos_match[1] : "_"
153
- key = error[:fragment].sub(/#\//, "").sub(/([0-9]+)[\/]?/, "")
154
- value = "Item ##{pos}. " + error[:message][0, error[:message].index(/ in schema/)].sub(/#\//, "").sub(/([0-9]+)[\/]?/, "")
155
- [key.to_sym, value]
156
- end
157
-
158
159
  def array!
159
160
  self.input = [*input]
160
161
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Strum
4
- VERSION = "0.0.56"
4
+ VERSION = "0.1.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.56
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Serhiy Nazarov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-18 00:00:00.000000000 Z
11
+ date: 2020-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json-schema
@@ -181,6 +181,7 @@ files:
181
181
  - Gemfile.lock
182
182
  - README.md
183
183
  - Rakefile
184
+ - bin/console
184
185
  - bin/strum
185
186
  - lib/strum.rb
186
187
  - lib/strum/Rakefile
@@ -201,6 +202,7 @@ files:
201
202
  - lib/strum/deep_keys_to_sym.rb
202
203
  - lib/strum/json.rb
203
204
  - lib/strum/json_deserializer.rb
205
+ - lib/strum/json_schema.rb
204
206
  - lib/strum/json_serializer.rb
205
207
  - lib/strum/object_to_hash.rb
206
208
  - lib/strum/pipe.rb