yaso 1.2.0 → 1.3.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 293839b577b5832d54938e07a07729d49ddd74fd226f0077076fe6f4986340ae
4
- data.tar.gz: 72d9d2bde9edbc0050f1473e3efc33a9c81952fe78906eaeb35acbba2ccc80bf
3
+ metadata.gz: 82a14582b1dadeb5c6103880c2ec7b3d7afe887ec9d8eb90601d77c02cfaf785
4
+ data.tar.gz: 94eab6547c4c0eaa87285bf09aa78534c33c06164fb98435dc7fe0b2f6d84d54
5
5
  SHA512:
6
- metadata.gz: a54b6acc15d5d8e71b25a4273ce87816ae58a1e63bd815e4cf338d671b5b71b3378016c076d9db44122e7612619e69e06c60e63cf7afd388b0de7509ad42ac0f
7
- data.tar.gz: 55a031ce994ac21ed04e659d70b2871cae67ed64d088799e26663b1d5e2ac5f76593d0ea4d0e3e181ff72b63fed7aa626abf67b063eed696be4418e74930e9e8
6
+ metadata.gz: 0104e325136a9952cff6309951c67915d015cf67897fcf257e73a51e335eb0d8e12bf87ecf2ec09bb5d326bf3c7622101f2b02a6c06deb75c16f511c91eff3a5
7
+ data.tar.gz: 04525a4314e1417f48f699e71d0b77ecf888ce44524e972fb2b811ddcfe9ef68f399c1771cf81031df6127d63287091e2b9fe36e3679cd0e6c26775554b7c3e7
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.1.2
1
+ 3.1.3
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- yaso (1.2.0)
4
+ yaso (1.3.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -14,7 +14,7 @@ GEM
14
14
  lefthook (1.0.5)
15
15
  method_source (1.0.0)
16
16
  parallel (1.22.1)
17
- parser (3.1.2.0)
17
+ parser (3.1.2.1)
18
18
  ast (~> 2.4.1)
19
19
  pry (0.14.1)
20
20
  coderay (~> 1.1)
@@ -29,13 +29,13 @@ GEM
29
29
  rspec-mocks (~> 3.11.0)
30
30
  rspec-core (3.11.0)
31
31
  rspec-support (~> 3.11.0)
32
- rspec-expectations (3.11.0)
32
+ rspec-expectations (3.11.1)
33
33
  diff-lcs (>= 1.2.0, < 2.0)
34
34
  rspec-support (~> 3.11.0)
35
35
  rspec-mocks (3.11.1)
36
36
  diff-lcs (>= 1.2.0, < 2.0)
37
37
  rspec-support (~> 3.11.0)
38
- rspec-support (3.11.0)
38
+ rspec-support (3.11.1)
39
39
  rubocop (1.28.2)
40
40
  parallel (~> 1.10)
41
41
  parser (>= 3.1.0.0)
@@ -59,10 +59,11 @@ GEM
59
59
  simplecov_json_formatter (~> 0.1)
60
60
  simplecov-html (0.12.3)
61
61
  simplecov_json_formatter (0.1.4)
62
- unicode-display_width (2.2.0)
62
+ unicode-display_width (2.3.0)
63
63
 
64
64
  PLATFORMS
65
65
  x86_64-darwin-21
66
+ x86_64-darwin-22
66
67
  x86_64-linux
67
68
 
68
69
  DEPENDENCIES
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  # Yaso
2
2
  [![Ruby](https://github.com/Ar2emis/yaso/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/Ar2emis/yaso/actions/workflows/main.yml) ![gem](https://img.shields.io/gem/v/yaso) [![GitHub license](https://img.shields.io/github/license/Ar2emis/yaso)](https://github.com/Ar2emis/yaso/blob/master/LICENSE.txt)
3
3
 
4
- That's my (Yet Another) ServiceObject pattern implementation. I made it fast ([the fastest actually](https://github.com/Ar2emis/yaso/wiki/Benchmarks)) and simple to use.
5
- I was inspired by those alternatives and I hope this will encourage them to be even better:
4
+ That's my (Yet Another) ServiceObject pattern implementation. I made it fast ([the fastest of this kind actually](https://github.com/Ar2emis/yaso/wiki/Benchmarks); [simple_command](https://github.com/nebulab/simple_command), you got me this time) and simple to use (I hope). I was inspired by those alternatives and I hope this will encourage them to be even better:
6
5
  - [Trailblazer](https://github.com/trailblazer/trailblazer)
7
6
  - [Decouplio](https://github.com/differencialx/decouplio)
8
7
 
@@ -28,7 +27,7 @@ All the information you can find in the gem [wiki](https://github.com/Ar2emis/ya
28
27
 
29
28
  ## Development
30
29
 
31
- I don't think that someone would like to help me developing the gem but if so just fork a new branch from the master, do your dark business, open a pull request and assign me as a reviewer.
30
+ I don't think that someone would like to help me developing the gem but if so just fork a repository, do your dark business, open a pull request and assign me as a reviewer.
32
31
 
33
32
  ## Contributing
34
33
 
data/benchmark/Gemfile CHANGED
@@ -3,11 +3,23 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gem 'benchmark-ips', '~> 2.10.0'
6
+
7
+ DRY_CONTAINER = {
8
+ '2.5' => '~> 0.7.2',
9
+ '2.6' => '~> 0.9.0'
10
+ }.freeze
11
+ gem 'dry-container', DRY_CONTAINER.fetch(RUBY_VERSION.match(/\A\d+\.\d+/)[0], '~> 0.11.0')
12
+ DRY_TRANSACTION = {
13
+ '2.5' => '~> 0.13.2',
14
+ '2.6' => '~> 0.13.3'
15
+ }.freeze
16
+ gem 'dry-transaction', DRY_TRANSACTION.fetch(RUBY_VERSION.match(/\A\d+\.\d+/)[0], '~> 0.15.0')
6
17
  gem 'interactor', '~> 3.1.2'
7
18
  gem 'kalibera', '~> 0.1.2'
8
19
  gem 'simple_command', RUBY_VERSION.include?('2.5') ? '~> 0.2.0' : '~> 1.0.1'
9
20
  gem 'trailblazer', '~> 2.1.0'
21
+ gem 'yaso', path: '..'
10
22
 
11
23
  gem 'active_interaction', %w[2.5 2.6].any? { |version| RUBY_VERSION.include?(version) } ? '~> 4.1.0' : '~> 5.1.0'
12
24
 
13
- RUBY_VERSION.include?('2.5') || gem('decouplio', '~> 1.0.0alpha8')
25
+ RUBY_VERSION.include?('2.5') || gem('decouplio', '~> 1.0.0rc')
data/benchmark/index.rb CHANGED
@@ -2,14 +2,16 @@
2
2
 
3
3
  require 'bundler/setup'
4
4
 
5
- require_relative '../lib/yaso'
6
-
7
5
  require 'benchmark/ips'
8
6
  RUBY_VERSION.include?('2.5') || require('decouplio')
9
7
  require 'interactor'
10
8
  require 'active_interaction'
11
9
  require 'trailblazer'
12
10
  require 'simple_command'
11
+ require 'yaso'
12
+ require 'dry/container'
13
+ require 'dry/transaction'
14
+ require 'dry/transaction/operation'
13
15
 
14
16
  require_relative 'shared/yaso_service'
15
17
  RUBY_VERSION.include?('2.5') || require_relative('shared/decouplio_service')
@@ -27,4 +29,5 @@ require_relative 'step/simple_command'
27
29
  require_relative 'step/interactor'
28
30
  require_relative 'step/active_interaction'
29
31
  require_relative 'step/trailblazer'
32
+ require_relative 'step/dry_transaction'
30
33
  require_relative 'step/benchmark'
@@ -13,6 +13,7 @@ Benchmark.ips do |x|
13
13
  x.report('Interactor') { InteractorStepsService.call }
14
14
  x.report('ActiveInteraction') { ActiveInteractionStepsService.run }
15
15
  x.report('Trailblazer') { TrailblazerStepsService.call }
16
+ x.report('DryTransaction') { DryTransactionStepsService.new.call({}) }
16
17
 
17
18
  x.compare!
18
19
  end
@@ -28,6 +29,7 @@ Benchmark.ips do |x|
28
29
  x.report('Interactor') { InteractorCallablesService.call }
29
30
  x.report('ActiveInteraction') { ActiveInteractionCallablesService.run }
30
31
  x.report('Trailblazer') { TrailblazerCallablesService.call }
32
+ x.report('DryTransaction') { DryTransactionCallablesService.new.call({}) }
31
33
 
32
34
  x.compare!
33
35
  end
@@ -56,7 +56,7 @@ class DecouplioStepsService < DecouplioService
56
56
  end
57
57
 
58
58
  class DecouplioCallableStep
59
- def self.call(ctx:, key:, value:, **)
59
+ def self.call(ctx, _, key:, value:, **)
60
60
  ctx[key] = value
61
61
  end
62
62
  end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DryTransactionStepsService
4
+ include Dry::Transaction
5
+
6
+ step :one
7
+ step :two
8
+ step :three
9
+ step :four
10
+ step :five
11
+ step :six
12
+ step :seven
13
+ step :eight
14
+ step :nine
15
+ step :ten
16
+
17
+ private
18
+
19
+ def one(ctx)
20
+ ctx[:one] = true
21
+ Success(ctx)
22
+ end
23
+
24
+ def two(ctx)
25
+ ctx[:two] = true
26
+ Success(ctx)
27
+ end
28
+
29
+ def three(ctx)
30
+ ctx[:three] = true
31
+ Success(ctx)
32
+ end
33
+
34
+ def four(ctx)
35
+ ctx[:four] = true
36
+ Success(ctx)
37
+ end
38
+
39
+ def five(ctx)
40
+ ctx[:five] = true
41
+ Success(ctx)
42
+ end
43
+
44
+ def six(ctx)
45
+ ctx[:six] = true
46
+ Success(ctx)
47
+ end
48
+
49
+ def seven(ctx)
50
+ ctx[:seven] = true
51
+ Success(ctx)
52
+ end
53
+
54
+ def eight(ctx)
55
+ ctx[:eight] = true
56
+ Success(ctx)
57
+ end
58
+
59
+ def nine(ctx)
60
+ ctx[:nine] = true
61
+ Success(ctx)
62
+ end
63
+
64
+ def ten(ctx)
65
+ ctx[:ten] = true
66
+ Success(ctx)
67
+ end
68
+ end
69
+
70
+ class DryTansactionCallable
71
+ include Dry::Transaction::Operation
72
+
73
+ def initialize(key)
74
+ @key = key
75
+ end
76
+
77
+ def call(ctx)
78
+ ctx[@key] = true
79
+ Success(ctx)
80
+ end
81
+ end
82
+
83
+ class DryTransactionContainer
84
+ extend Dry::Container::Mixin
85
+
86
+ namespace :callable do
87
+ register(:one) { DryTansactionCallable.new(:one) }
88
+ register(:two) { DryTansactionCallable.new(:two) }
89
+ register(:three) { DryTansactionCallable.new(:three) }
90
+ register(:four) { DryTansactionCallable.new(:four) }
91
+ register(:five) { DryTansactionCallable.new(:five) }
92
+ register(:six) { DryTansactionCallable.new(:six) }
93
+ register(:seven) { DryTansactionCallable.new(:seven) }
94
+ register(:eight) { DryTansactionCallable.new(:eight) }
95
+ register(:nine) { DryTansactionCallable.new(:nine) }
96
+ register(:ten) { DryTansactionCallable.new(:ten) }
97
+ end
98
+ end
99
+
100
+ class DryTransactionCallablesService
101
+ include Dry::Transaction(container: DryTransactionContainer)
102
+
103
+ step :one, with: :'callable.one'
104
+ step :two, with: :'callable.two'
105
+ step :three, with: :'callable.three'
106
+ step :four, with: :'callable.four'
107
+ step :five, with: :'callable.five'
108
+ step :six, with: :'callable.six'
109
+ step :seven, with: :'callable.seven'
110
+ step :eight, with: :'callable.eight'
111
+ step :nine, with: :'callable.nine'
112
+ step :ten, with: :'callable.ten'
113
+ end
@@ -64,7 +64,7 @@ module TrailblazerMacro
64
64
  ctx[:"result.#{id}"] = Trailblazer::Operation::Result.new(false, {})
65
65
  false
66
66
  end
67
- task = Trailblazer::Activity::TaskBuilder::Binary(step)
67
+ task = Trailblazer::Activity::Circuit::TaskAdapter.for_step(step)
68
68
  { task: task, id: id }
69
69
  end
70
70
  # rubocop:enable Naming/MethodName
data/docker/Dockerfile ADDED
@@ -0,0 +1,7 @@
1
+ ARG VERSION=latest
2
+
3
+ FROM ruby:${VERSION}
4
+
5
+ ENTRYPOINT [ "/yaso/docker/entrypoint.sh" ]
6
+
7
+ WORKDIR /yaso/benchmark
@@ -0,0 +1,15 @@
1
+ #!/bin/bash
2
+
3
+ if [[ `bundle -v` =~ "Bundler version 2" ]]; then
4
+ bundle config set --local path '/bundle/cache'
5
+ bundle config set --local without 'development'
6
+ else
7
+ bundle config --local path '/bundle/cache'
8
+ bundle config --local without 'development'
9
+ fi
10
+
11
+ bundle
12
+
13
+ ruby index.rb
14
+
15
+ rm Gemfile.lock
@@ -0,0 +1,9 @@
1
+ services:
2
+ benchmark:
3
+ build: docker
4
+ volumes:
5
+ - .:/yaso
6
+ - bundle:/bundle/cache
7
+
8
+ volumes:
9
+ bundle:
@@ -7,12 +7,12 @@ module Yaso
7
7
  YASO = :yaso
8
8
 
9
9
  class << self
10
- def call(object, options: {}, **)
10
+ def call(object, options: {}, with_block: false, **)
11
11
  type = object_type(object)
12
12
  invocable = case type
13
- when YASO then proc { |context, _| object.call(context.clone).success? }
14
- when CALLABLE then proc { |context, _, &block| object.call(context, **options, &block) }
15
- else method_invocable(object)
13
+ when YASO then proc { |context| object.call(context).success? }
14
+ when CALLABLE then callable_invocable(object, options, with_block: with_block)
15
+ else method_invocable(object, with_block: with_block)
16
16
  end
17
17
  [type, invocable]
18
18
  end
@@ -25,11 +25,25 @@ module Yaso
25
25
  object < ::Yaso::Service ? Invocable::YASO : Invocable::CALLABLE
26
26
  end
27
27
 
28
- def method_invocable(object)
28
+ def callable_invocable(object, options, with_block:)
29
+ return proc { |context, &block| object.call(context, **options, &block) } if with_block
30
+
31
+ proc { |context| object.call(context, **options) }
32
+ end
33
+
34
+ def method_invocable(object, with_block:)
35
+ if with_block
36
+ return instance_eval <<-RUBY, __FILE__, __LINE__ + 1
37
+ proc { |context, instance, &block| # proc { |context, instance, &block|
38
+ instance.#{object}(context, **context, &block) # instance.<method_name>(context, **context, &block)
39
+ } # }
40
+ RUBY
41
+ end
42
+
29
43
  instance_eval <<-RUBY, __FILE__, __LINE__ + 1
30
- proc { |context, instance, &block| # proc { |context, instance, &block|
31
- instance.#{object}(context, **context.data, &block) # instance.<method_name>(context, **context.data, &block)
32
- } # }
44
+ proc { |context, instance| # proc { |context, instance|
45
+ instance.#{object}(context, **context) # instance.<method_name>(context, **context)
46
+ } # }
33
47
  RUBY
34
48
  end
35
49
  end
@@ -4,7 +4,7 @@ module Yaso
4
4
  module Logic
5
5
  class Failure < Base
6
6
  def call(context, instance)
7
- context.success = false
7
+ instance.success = false
8
8
  @invocable.call(context, instance) ? @next_step : @failure
9
9
  end
10
10
  end
@@ -4,7 +4,7 @@ module Yaso
4
4
  module Logic
5
5
  class Pass < Base
6
6
  def call(context, instance)
7
- context.success = true
7
+ instance.success = true
8
8
  @invocable.call(context, instance) ? @next_step : @failure
9
9
  end
10
10
  end
@@ -4,11 +4,11 @@ module Yaso
4
4
  module Logic
5
5
  class Step < Base
6
6
  def call(context, instance)
7
- context.success = true
7
+ instance.success = true
8
8
  if @invocable.call(context, instance)
9
9
  @next_step
10
10
  else
11
- context.success = false
11
+ instance.success = false
12
12
  @failure
13
13
  end
14
14
  end
@@ -16,8 +16,8 @@ module Yaso
16
16
  end
17
17
 
18
18
  def call(object:, category:, block:, **opts)
19
- invocable_type, invocable = Invocable.call(object, **opts)
20
19
  logic_class = CATEGORIES[category]
20
+ invocable_type, invocable = Invocable.call(object, with_block: logic_class == Wrap, **opts)
21
21
  if invocable_type == Invocable::METHOD
22
22
  opts[:name] = logic_class == Switch ? build_switch(object, **opts, &block) : build_method(object, &block)
23
23
  end
@@ -51,14 +51,11 @@ module Yaso
51
51
  end
52
52
 
53
53
  def build_wrapper_methods(wrapper_class, service_class)
54
- wrapper_class.define_singleton_method(:flow) do
55
- service_class.flow
56
- end
57
54
  wrapper_class.define_singleton_method(:call) do |context, instance|
58
- @entry ||= flow.call(service_class, steps)
55
+ @entry ||= service_class.flow.call(service_class, steps)
59
56
  step = @entry
60
57
  step = step.call(context, instance) while step
61
- context
58
+ instance
62
59
  end
63
60
  end
64
61
  end
@@ -4,13 +4,12 @@ module Yaso
4
4
  module Logic
5
5
  class Switch < Base
6
6
  def call(context, instance)
7
- context.success = true
7
+ instance.success = true
8
8
  switch_case = @invocable.call(context, instance) || raise(UnhandledSwitchCaseError, instance.class)
9
-
10
9
  if Invocable.call(switch_case).last.call(context, instance)
11
10
  @next_step
12
11
  else
13
- context.success = false
12
+ instance.success = false
14
13
  @failure
15
14
  end
16
15
  end
@@ -9,11 +9,12 @@ module Yaso
9
9
  end
10
10
 
11
11
  def call(context, instance)
12
- context.success = true
13
- if @invocable.call(context, instance) { @wrapper.call(context, instance).success? }
12
+ instance.success = true
13
+ result = @invocable.call(context, instance) { @wrapper.call(context, instance).success? }
14
+ if result
14
15
  @next_step
15
16
  else
16
- context.success = false
17
+ instance.success = false
17
18
  @failure
18
19
  end
19
20
  end
data/lib/yaso/service.rb CHANGED
@@ -4,14 +4,44 @@ module Yaso
4
4
  class Service
5
5
  extend Stepable
6
6
 
7
+ attr_writer :success
8
+
9
+ def initialize(context)
10
+ @context = context
11
+ @success = true
12
+ end
13
+
14
+ def [](key)
15
+ @context[key]
16
+ end
17
+
18
+ def []=(key, value)
19
+ @context[key] = value
20
+ end
21
+
22
+ def success?
23
+ @success
24
+ end
25
+
26
+ def failure?
27
+ !@success
28
+ end
29
+
30
+ def to_h
31
+ @context.dup
32
+ end
33
+
34
+ def inspect
35
+ "Result:#{self.class} successful: #{@success}, context: #{@context}"
36
+ end
37
+
7
38
  class << self
8
39
  def call(context = {})
9
- context = context.is_a?(Context) ? context : Context.new(context)
10
40
  @entry ||= flow.call(self, steps)
11
41
  step = @entry
12
- instance = new
42
+ instance = new(context)
13
43
  step = step.call(context, instance) while step
14
- context
44
+ instance
15
45
  end
16
46
 
17
47
  def flow(name = nil)
data/lib/yaso/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Yaso
4
- VERSION = '1.2.0'
4
+ VERSION = '1.3.1'
5
5
  end
data/lib/yaso.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require_relative 'yaso/version'
4
4
  require_relative 'yaso/errors'
5
- require_relative 'yaso/context'
6
5
  require_relative 'yaso/invocable'
7
6
  require_relative 'yaso/stepable'
8
7
  require_relative 'yaso/logic'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yaso
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artem Shevchenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-27 00:00:00.000000000 Z
11
+ date: 2022-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffaker
@@ -203,14 +203,17 @@ files:
203
203
  - benchmark/step/active_interaction.rb
204
204
  - benchmark/step/benchmark.rb
205
205
  - benchmark/step/decouplio.rb
206
+ - benchmark/step/dry_transaction.rb
206
207
  - benchmark/step/interactor.rb
207
208
  - benchmark/step/pure.rb
208
209
  - benchmark/step/simple_command.rb
209
210
  - benchmark/step/trailblazer.rb
210
211
  - benchmark/step/yaso.rb
212
+ - docker-compose.yml
213
+ - docker/Dockerfile
214
+ - docker/entrypoint.sh
211
215
  - lefthook.yml
212
216
  - lib/yaso.rb
213
- - lib/yaso/context.rb
214
217
  - lib/yaso/errors.rb
215
218
  - lib/yaso/invocable.rb
216
219
  - lib/yaso/logic.rb
@@ -248,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
248
251
  - !ruby/object:Gem::Version
249
252
  version: '0'
250
253
  requirements: []
251
- rubygems_version: 3.3.7
254
+ rubygems_version: 3.3.26
252
255
  signing_key:
253
256
  specification_version: 4
254
257
  summary: Yet Another Service Object
data/lib/yaso/context.rb DELETED
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Yaso
4
- class Context
5
- attr_writer :success
6
- attr_reader :data
7
-
8
- def initialize(kwargs)
9
- @success = true
10
- @data = kwargs
11
- end
12
-
13
- def [](key)
14
- @data[key]
15
- end
16
-
17
- def []=(key, value)
18
- @data[key] = value
19
- end
20
-
21
- def to_h
22
- @data.dup
23
- end
24
-
25
- def success?
26
- @success
27
- end
28
-
29
- def failure?
30
- !@success
31
- end
32
- end
33
- end