trailblazer-operation 0.6.3 → 0.7.1

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: b3e5248a8515b6f1255116f82ba2b0fc2836b373dcbe03d38fb5c0b93f94c82a
4
- data.tar.gz: 185922dd1990ae902d2ed5fd4639c0d2788913d63036eb71542945b15eb1995c
3
+ metadata.gz: 63f655777a97401ddf1ae5b1706757a7b284efbc6d5545397c00da0b4904a606
4
+ data.tar.gz: 71b308182ed3ad9c27333c0fd818ec017309002a1c7588adf64a85b54fde714e
5
5
  SHA512:
6
- metadata.gz: a4f01d8601c8e97e72f1cabb52adabd9371d416472fa1784573aa13cc1252108f2c5a6f12157e7e3379f21cfb7b7ebe2d5f1213813473a6796f05a6652b8cc55
7
- data.tar.gz: ff7522a5ec8c73ad8ec76ef2e3f2019309fa2d9f708463c9e6b96a83cc07ac8cc6878714b4f730d4701848b69ceec11a999b65c5576514292f0da1b56c27b41a
6
+ metadata.gz: d2372fb0f13931fb7e08a2e60cff6d9f4850b74a3d17b5661ad3a9853a460fd855656117387d685d6135306d1f67e27e26350c5e1ef07b29c2b16990fda5c874
7
+ data.tar.gz: cda2f29f0892f0d7c20d5c8af862e1076bec5a2c8849c307d53af92b09214720293e637fd6163690a76e7c9de282017743eb9c31107f3648329300a076d650db
data/.travis.yml CHANGED
@@ -1,16 +1,11 @@
1
1
  language: ruby
2
- before_install:
3
- - gem install bundler -v 1.17.3
4
- matrix:
5
- include:
6
- # - rvm: 2.1.0
7
- # gemfile: Gemfile
8
- - rvm: 2.2.4
9
- gemfile: Gemfile
10
- - rvm: 2.3.3
11
- gemfile: Gemfile
12
- - rvm: 2.4.0
13
- gemfile: Gemfile
14
- - rvm: 2.5.0
15
- gemfile: Gemfile
16
- script: bundle exec rake test
2
+ rvm:
3
+ - ruby-head
4
+ - 3.0
5
+ - 2.7
6
+ - 2.6
7
+ - 2.5
8
+ - 2.4
9
+ jobs:
10
+ allow_failures:
11
+ - rvm: ruby-head
data/CHANGES.md CHANGED
@@ -1,3 +1,26 @@
1
+ ## 0.7.1
2
+
3
+ * In `Operation.call_with_public_interface`, pass `self` and not `@activity` to the `invoke`r. This fixes tracing as it now catches the actual Operation class, not an activity instance.
4
+
5
+ ## 0.7.0
6
+
7
+ * Compatible with Ruby 2.4-3.0.
8
+ * Add `Operation.wtf?`.
9
+ * Add `Operation.call_with_flow_options` to allow using explicit aliasing in Ruby < 3.0.
10
+
11
+ ## 0.6.6
12
+
13
+ * Rename `Operation.flow_options` to `Operation.flow_options_for_public_call`.
14
+ * Operations can also accept `flow_options` at run-time now :beers:, giving them precedence over `Operation.flow_options_for_public_call`.
15
+
16
+ ## 0.6.5
17
+
18
+ * Upgrade `trailblazer-activity` & `trailblazer-activity-dsl-linear` versions to utilise new `trailblazer-context` :drum:
19
+
20
+ ## 0.6.4
21
+
22
+ * Remove container support. Containers should be part of `ctx` itself
23
+
1
24
  ## 0.6.3
2
25
 
3
26
  * Require forwardable module from standard lib.
data/Gemfile CHANGED
@@ -10,8 +10,9 @@ gem "dry-auto_inject"
10
10
  gem "benchmark-ips"
11
11
  gem "minitest-line"
12
12
 
13
- # gem "trailblazer-developer", path: "../developer"
13
+ # gem "trailblazer-developer", path: "../trailblazer-developer"
14
14
  # gem "trailblazer-developer", git: "https://github.com/trailblazer/trailblazer-developer"
15
15
  # gem "trailblazer-activity", path: "../trailblazer-activity"
16
+ # gem "trailblazer-context", path: "../trailblazer-context"
16
17
  # gem "trailblazer-activity-dsl-linear", path: "../trailblazer-activity-dsl-linear"
17
18
  # gem "trailblazer-activity", github: "trailblazer/trailblazer-activity"
data/Rakefile CHANGED
@@ -4,18 +4,7 @@ require "rake/testtask"
4
4
  Rake::TestTask.new(:test) do |test|
5
5
  test.libs << "test"
6
6
  test.verbose = true
7
-
8
- test_files = FileList["test/**/*_test.rb"]
9
-
10
- if RUBY_VERSION == "2.0.0"
11
- # test_files = test_files - %w{test/dry_container_test.rb test/2.1.0-pipetree_test.rb}
12
- test_files = test_files - %w{test/step_test.rb} + %w{test/ruby-2.0.0/step_test.rb}
13
- test_files = test_files - %w{test/operation_test.rb} + %w{test/ruby-2.0.0/operation_test.rb}
14
- else
15
- test_files -= FileList["test/ruby-2.0.0/*"]
16
- end
17
-
18
- test.test_files = test_files
7
+ test.test_files = FileList["test/**/*_test.rb"]
19
8
  end
20
9
 
21
10
  task :default => %i[test]
@@ -1,7 +1,7 @@
1
1
  require 'forwardable'
2
+ require 'trailblazer/operation/version'
2
3
  require "trailblazer/option"
3
4
  require "trailblazer/context"
4
- require "trailblazer/container_chain"
5
5
 
6
6
  require "trailblazer/activity/dsl/linear"
7
7
 
@@ -51,27 +51,13 @@ module Trailblazer
51
51
 
52
52
  require "trailblazer/operation/trace"
53
53
  extend Trace # ::trace
54
-
55
- module Railway
56
- def self.fail! ; Activity::Left end
57
- def self.pass! ; Activity::Right end
58
- def self.fail_fast!; Activity::FastTrack::FailFast end
59
- def self.pass_fast!; Activity::FastTrack::PassFast end
60
- end
61
54
  end
62
55
  end
63
56
 
64
- require 'trailblazer/operation/version'
65
-
66
57
  require "trailblazer/operation/class_dependencies"
67
58
  require "trailblazer/operation/deprecated_macro" # TODO: remove in 2.2.
68
59
 
69
60
  require "trailblazer/operation/result"
70
61
  require "trailblazer/operation/railway"
71
62
 
72
- require "trailblazer/developer"
73
- require "trailblazer/operation/trace"
74
-
75
63
  require "trailblazer/operation/railway/macaroni"
76
-
77
- require "trailblazer/operation/container"
@@ -12,23 +12,23 @@ class Trailblazer::Operation
12
12
  @state.update_options(options)
13
13
  end
14
14
 
15
- def options_for_public_call(options, *)
15
+ def options_for_public_call(options, flow_options)
16
16
  ctx = super
17
- context_for_fields(class_fields, ctx)
17
+ context_for_fields(class_fields, [ctx, flow_options])
18
18
  end
19
19
 
20
20
  private def class_fields
21
21
  @state.to_h[:fields]
22
22
  end
23
23
 
24
- private def context_for_fields(fields, ctx)
25
- ctx_with_fields = Trailblazer::Context.implementation.build(fields, ctx, [ctx, {}], {}) # TODO: redundant to otions_for_public_call. how to inject aliasing etc?
24
+ private def context_for_fields(fields, (ctx, flow_options), **)
25
+ ctx_with_fields = Trailblazer::Context(fields, ctx, flow_options[:context_options]) # TODO: redundant to otions_for_public_call.
26
26
  end
27
27
 
28
28
  def call_with_circuit_interface((ctx, flow_options), **circuit_options)
29
- ctx_with_fields = context_for_fields(class_fields, ctx)
29
+ ctx_with_fields = context_for_fields(class_fields, [ctx, flow_options], **circuit_options)
30
30
 
31
- super([ctx_with_fields, flow_options], circuit_options) # FIXME: should we unwrap here?
31
+ super([ctx_with_fields, flow_options], **circuit_options) # FIXME: should we unwrap here?
32
32
  end
33
33
  end
34
34
  end
@@ -13,21 +13,32 @@ module Trailblazer
13
13
  #
14
14
  # @note Do not override this method as it will be removed in future versions. Also, you will break tracing.
15
15
  # @return Operation::Railway::Result binary result object
16
- def call(options = {}, *args)
17
- return call_with_circuit_interface(options, *args) if options.is_a?(Array) # This is kind of a hack that could be well hidden if Ruby had method overloading. Goal is to simplify the call/__call__ thing as we're fading out Operation::call anyway.
16
+ def call(options = {}, flow_options = {}, **circuit_options)
17
+ return call_with_circuit_interface(options, **circuit_options) if options.is_a?(Array) # This is kind of a hack that could be well hidden if Ruby had method overloading. Goal is to simplify the call/__call__ thing as we're fading out Operation::call anyway.
18
18
 
19
- call_with_public_interface(options, *args)
19
+ call_with_public_interface(options, flow_options, **circuit_options)
20
20
  end
21
21
 
22
- def call_with_public_interface(*args)
23
- ctx = options_for_public_call(*args, flow_options())
22
+ # Default {@activity} call interface which doesn't accept {circuit_options}
23
+ #
24
+ # @param [Array] args => [ctx, flow_options]
25
+ #
26
+ # @return [Operation::Railway::Result]
27
+ #
28
+ # @private
29
+ def call_with_public_interface(options, flow_options, invoke_class: Activity::TaskWrap, **circuit_options)
30
+ flow_options = flow_options_for_public_call(flow_options)
31
+
32
+ options = circuit_options.any? ? circuit_options : options # This is needed in Ruby 3 for {Create.(params: {})} calls.
33
+
34
+
35
+ ctx = options_for_public_call(options, flow_options)
24
36
 
25
37
  # call the activity.
26
38
  # This will result in invoking {::call_with_circuit_interface}.
27
- # last_signal, (options, flow_options) = Activity::TaskWrap.invoke(self, [ctx, {}], {})
28
- signal, (ctx, flow_options) = Activity::TaskWrap.invoke(
29
- @activity,
30
- [ctx, flow_options()],
39
+ signal, (ctx, flow_options) = invoke_class.invoke(
40
+ self,
41
+ [ctx, flow_options],
31
42
  exec_context: new
32
43
  )
33
44
 
@@ -36,8 +47,15 @@ module Trailblazer
36
47
  end
37
48
 
38
49
  # This interface is used for all nested OPs (and the outer-most, too).
39
- def call_with_circuit_interface(args, circuit_options)
40
- strategy_call(args, circuit_options) # FastTrack#call
50
+ #
51
+ # @param [Array] args - Contains [ctx, flow_options]
52
+ # @param [Hash] circuit_options - Options to configure activity circuit
53
+ #
54
+ # @return [signal, [ctx, flow_options]]
55
+ #
56
+ # @private
57
+ def call_with_circuit_interface(args, **circuit_options)
58
+ strategy_call(args, **circuit_options) # FastTrack#call
41
59
  end
42
60
 
43
61
  def options_for_public_call(*args)
@@ -46,13 +64,19 @@ module Trailblazer
46
64
 
47
65
  # Compile a Context object to be passed into the Activity::call.
48
66
  # @private
49
- def self.options_for_public_call(options, **flow_options)
50
- Trailblazer::Context.for_circuit(options, {}, [options, flow_options], {})
67
+ def self.options_for_public_call(options, flow_options = {})
68
+ Trailblazer::Context(options, {}, flow_options[:context_options])
51
69
  end
52
70
 
53
71
  # @semi=public
54
- def flow_options
55
- {context_alias: {}}
72
+ def flow_options_for_public_call(options = {})
73
+ options
74
+ end
75
+
76
+ # TODO: remove when we stop supporting < 3.0.
77
+ def call_with_flow_options(options, flow_options)
78
+ raise "[Trailblazer] `Operation.call_with_flow_options is deprecated in Ruby 3.0. Use `Operation.(options, flow_options)`" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0.0")
79
+ call_with_public_interface(options, flow_options, {invoke_class: Activity::TaskWrap})
56
80
  end
57
81
  end
58
82
  end
@@ -5,6 +5,10 @@ module Trailblazer
5
5
  class Operation
6
6
  # End event: All subclasses of End:::Success are interpreted as "success".
7
7
  module Railway
8
+ def self.fail! ; Activity::Left end
9
+ def self.pass! ; Activity::Right end
10
+ def self.fail_fast!; Activity::FastTrack::FailFast end
11
+ def self.pass_fast!; Activity::FastTrack::PassFast end
8
12
  # @param options Context
9
13
  # @param end_event The last emitted signal in a circuit is usually the end event.
10
14
  def self.Result(end_event, options, *)
@@ -1,10 +1,12 @@
1
1
  require 'delegate'
2
+ require "trailblazer/developer"
2
3
 
3
4
  module Trailblazer
4
5
  class Operation
5
6
  module Trace
6
7
  # @note The problem in this method is, we have redundancy with Operation::PublicCall
7
8
  def self.call(operation, options)
9
+ # warn %{Trailblazer: `Operation.trace` is deprecated. Please use `Operation.wtf?`.} # DISCUSS: should this be deprecated?
8
10
  ctx = PublicCall.options_for_public_call(options) # redundant with PublicCall::call.
9
11
 
10
12
  stack, signal, (ctx, _flow_options) = Developer::Trace.(operation, [ctx, {}])
@@ -24,6 +26,10 @@ module Trailblazer
24
26
  Trace.(self, options)
25
27
  end
26
28
 
29
+ def wtf?(options)
30
+ call_with_public_interface(options, {}, invoke_class: Developer::Wtf)
31
+ end
32
+
27
33
  # Presentation of the traced stack via the returned result object.
28
34
  # This object is wrapped around the original result in {Trace.call}.
29
35
  class Result < ::SimpleDelegator
@@ -1,5 +1,7 @@
1
1
  module Trailblazer
2
- class Operation
3
- VERSION = "0.6.3"
2
+ module Version
3
+ module Operation
4
+ VERSION = "0.7.1"
5
+ end
4
6
  end
5
7
  end
@@ -1,31 +1,31 @@
1
- require "test_helper"
1
+ # require "test_helper"
2
2
 
3
- class MacaroniTaskBuilderTest < Minitest::Spec
4
- Memo = Struct.new(:title) do
5
- def save
6
- self.title = title[:title].reverse
7
- end
8
- end
3
+ # class MacaroniTaskBuilderTest < Minitest::Spec
4
+ # Memo = Struct.new(:title) do
5
+ # def save
6
+ # self.title = title[:title].reverse
7
+ # end
8
+ # end
9
9
 
10
- #:create
11
- class Memo::Create < Trailblazer::Operation(step_interface_builder: Trailblazer::Operation::Railway::KwSignature)
12
- #~ign
13
- step :create_model
14
- step :save
15
- #~ign end
16
- #~methods
17
- def create_model(params:, options:, **)
18
- options[:model] = Memo.new(title: params[:title])
19
- end
10
+ # #:create
11
+ # class Memo::Create < Trailblazer::Operation(step_interface_builder: Trailblazer::Operation::Railway::KwSignature)
12
+ # #~ign
13
+ # step :create_model
14
+ # step :save
15
+ # #~ign end
16
+ # #~methods
17
+ # def create_model(params:, options:, **)
18
+ # options[:model] = Memo.new(title: params[:title])
19
+ # end
20
20
 
21
- def save(model:, **)
22
- model.save
23
- end
24
- #~methods end
25
- end
26
- #:create end
21
+ # def save(model:, **)
22
+ # model.save
23
+ # end
24
+ # #~methods end
25
+ # end
26
+ # #:create end
27
27
 
28
- it "allows optional macaroni call style" do
29
- Memo::Create.(params: {title: "Wow!"}).inspect(:model).must_equal %{<Result:true [#<struct MacaroniTaskBuilderTest::Memo title=\"!woW\">] >}
30
- end
31
- end
28
+ # it "allows optional macaroni call style" do
29
+ # Memo::Create.(params: {title: "Wow!"}).inspect(:model).must_equal %{<Result:true [#<struct MacaroniTaskBuilderTest::Memo title=\"!woW\">] >}
30
+ # end
31
+ # end
@@ -24,7 +24,6 @@ class DocsActivityTest < Minitest::Spec
24
24
  signal.inspect.must_equal %{#<Trailblazer::Activity::Railway::End::Success semantic=:success>}
25
25
  end
26
26
 
27
- #:describe
28
27
  describe Memo::Create do
29
28
  it "creates a sane Memo instance" do
30
29
  #:call-public
@@ -39,8 +38,69 @@ class DocsActivityTest < Minitest::Spec
39
38
  result.success?.must_equal true
40
39
  result[:model].text.must_equal "Enjoy an IPA"
41
40
  end
41
+
42
+ it "allows indifferent access for ctx keys" do
43
+ #:ctx-indifferent-access
44
+ result = Memo::Create.(params: { text: "Enjoy an IPA" })
45
+
46
+ result[:params] # => { text: "Enjoy an IPA" }
47
+ result['params'] # => { text: "Enjoy an IPA" }
48
+ #:ctx-indifferent-access end
49
+
50
+ result.success?.must_equal true
51
+ result[:params].must_equal({ text: "Enjoy an IPA" })
52
+ result['params'].must_equal({ text: "Enjoy an IPA" })
53
+ end
54
+
55
+ it "allows defining aliases for ctx keys" do
56
+ module AliasesExample
57
+ Memo = Struct.new(:text)
58
+
59
+ module Memo::Contract
60
+ Create = Struct.new(:sync)
61
+ end
62
+
63
+ #:ctx-aliases-step
64
+ class Memo::Create < Trailblazer::Operation
65
+ #~flow
66
+ step ->(ctx, **) { ctx[:'contract.default'] = Memo::Contract::Create.new }
67
+ #~flow end
68
+
69
+ pass :sync
70
+
71
+ def sync(ctx, contract:, **)
72
+ # ctx['contract.default'] == ctx[:contract]
73
+ contract.sync
74
+ end
75
+ end
76
+ #:ctx-aliases-step end
77
+ end
78
+
79
+ #:ctx-aliases
80
+ options = { params: { text: "Enjoy an IPA" } }
81
+ flow_options = {
82
+ context_options: {
83
+ aliases: { 'contract.default': :contract, 'policy.default': :policy },
84
+ container_class: Trailblazer::Context::Container::WithAliases,
85
+ }
86
+ }
87
+
88
+ # Sorry, this feature is only reliable in Ruby > 2.7
89
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0.0")
90
+ result = AliasesExample::Memo::Create.(options, flow_options)
91
+ else # Ruby 2.6 etc
92
+ result = AliasesExample::Memo::Create.call_with_flow_options(options, flow_options)
93
+ end
94
+
95
+ result['contract.default'] # => Memo::Contract::Create
96
+ result[:contract] # => Memo::Contract::Create
97
+ #:ctx-aliases end
98
+
99
+ result.success?.must_equal true
100
+ _(result[:contract].class).must_equal AliasesExample::Memo::Contract::Create
101
+ _(result['contract.default']).must_equal result[:contract]
102
+ end
42
103
  end
43
- #:describe end
44
104
 
45
105
  it do
46
106
  module J
@@ -245,9 +245,8 @@ describe all options :pass_fast, :fast_track and emiting signals directly, like
245
245
  end
246
246
 
247
247
  it "runs #create_model, only" do
248
- Memo = FastTrack::Memo
249
248
  #:ft-call
250
- result = Memo::Create.(create_empty_model: true)
249
+ result = FastTrack::Memo::Create.(create_empty_model: true)
251
250
  puts result.success? #=> true
252
251
  puts result[:model].inspect #=> #<Memo text=nil>
253
252
  #:ft-call end
@@ -257,9 +256,8 @@ describe all options :pass_fast, :fast_track and emiting signals directly, like
257
256
  end
258
257
 
259
258
  it "fast-tracks in #assign_errors" do
260
- Memo = FastTrack::Memo
261
259
  #:ft-call-err
262
- result = Memo::Create.({})
260
+ result = FastTrack::Memo::Create.({})
263
261
  puts result.success? #=> false
264
262
  puts result[:model].inspect #=> #<Memo text=nil>
265
263
  puts result[:errors].inspect #=> "Something went wrong!"
@@ -271,16 +269,15 @@ describe all options :pass_fast, :fast_track and emiting signals directly, like
271
269
  end
272
270
 
273
271
  it "goes till #save by emitting signals directly" do
274
- Memo = FastTrack::Memo
275
- result = Memo::Create.(params: {text: "Punk is not dead!"})
272
+ result = FastTrack::Memo::Create.(params: {text: "Punk is not dead!"})
276
273
  result.success?.must_equal true
277
274
  result[:model].id.must_equal 1
278
275
  result[:errors].must_be_nil
279
276
  end
280
277
 
278
+
281
279
  it "goes till #save by using signal helper" do
282
- Memo = FastTrack::Memo
283
- result = Memo::Create2.(params: {text: "Punk is not dead!"})
280
+ result = FastTrack::Memo::Create2.(params: {text: "Punk is not dead!"})
284
281
  result.success?.must_equal true
285
282
  result[:model].id.must_equal 1
286
283
  result[:errors].must_be_nil
@@ -79,8 +79,63 @@ class DeclarativeApiTest < Minitest::Spec
79
79
  step ->(options, **) { options["e"] = 2 }
80
80
  end
81
81
 
82
+ class Aliases < Update
83
+ def self.flow_options_for_public_call(*)
84
+ {
85
+ context_options: {
86
+ aliases: { 'b' => :settle },
87
+ container_class: Trailblazer::Context::Container::WithAliases,
88
+ }
89
+ }
90
+ end
91
+ end
92
+
82
93
  it "allows to inherit" do
83
94
  Upsert.("params" => {decide: true}).inspect("a", "b", "c", "d", "e").must_equal %{<Result:true [false, true, nil, 1, nil] >}
84
95
  Unset. ("params" => {decide: true}).inspect("a", "b", "c", "d", "e").must_equal %{<Result:true [false, true, nil, 1, 2] >}
85
96
  end
97
+
98
+ #---
99
+ #- ctx container
100
+ it do
101
+ options = { "params" => {decide: true} }
102
+
103
+ # Default call
104
+ result = Update.(options)
105
+ result.inspect("a", "b", "c").must_equal %{<Result:true [false, true, nil] >}
106
+
107
+ # Circuit interface call
108
+ signal, (ctx, _) = Update.([Update.options_for_public_call(options), {}], **{})
109
+
110
+ signal.inspect.must_equal %{#<Trailblazer::Activity::Railway::End::Success semantic=:success>}
111
+ ctx.inspect.must_equal %{#<Trailblazer::Context::Container wrapped_options={\"params\"=>{:decide=>true}} mutable_options={\"a\"=>false, \"b\"=>true}>}
112
+
113
+ # Call by passing aliases as an argument.
114
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0.0")
115
+ result = Update.(
116
+ options,
117
+ {
118
+ context_options: {
119
+ aliases: { 'b' => :settle },
120
+ container_class: Trailblazer::Context::Container::WithAliases,
121
+ }
122
+ }
123
+ )
124
+ else
125
+ result = Update.call_with_flow_options(
126
+ options,
127
+ {
128
+ context_options: {
129
+ aliases: { 'b' => :settle },
130
+ container_class: Trailblazer::Context::Container::WithAliases,
131
+ }
132
+ },
133
+ )
134
+ end
135
+
136
+ result[:settle].must_equal true
137
+ # Set aliases by overriding `flow_options` at the compile time.
138
+ result = Aliases.(options)
139
+ result[:settle].must_equal true
140
+ end
86
141
  end
data/test/step_test.rb CHANGED
@@ -40,7 +40,11 @@ class StepTest < Minitest::Spec
40
40
 
41
41
  it { Create.(a: 1, b: 2, c: 3, d: 4, e: 5).inspect("a", "b", "c", "d", "e").must_equal "<Result:true [1, 2, 3, 4, 5] >" }
42
42
 
43
- it { Trailblazer::Developer.railway(Create).gsub(/0x.+?step_test.rb/, "").must_equal %{[>#<Proc::30 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c>,>d,>MyMacro]} }
43
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0")
44
+ it { Trailblazer::Developer.railway(Create).gsub(/0x.+?step_test.rb/, "").gsub(/\)\s.+?step_test.rb/, ") test/step_test.rb").must_equal %{[>#<Proc::30 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c(options, c: ..., **) test/step_test.rb:18>,>d,>MyMacro]} }
45
+ else
46
+ it { Trailblazer::Developer.railway(Create).gsub(/0x.+?step_test.rb/, "").must_equal %{[>#<Proc::30 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c>,>d,>MyMacro]} }
47
+ end
44
48
 
45
49
  #---
46
50
  #- :before, :after, :replace, :delete, :override
@@ -174,11 +178,20 @@ class StepTest < Minitest::Spec
174
178
  # not existent :name
175
179
  it do
176
180
  op = assert_raises Trailblazer::Activity::DSL::Linear::Sequence::IndexError do
177
- Class.new(Trailblazer::Operation) do
181
+ class InvalidStep < Trailblazer::Operation
178
182
  step :a, before: "I don't exist!"
179
183
  end
180
184
  end
181
- assert_match /<Trailblazer::Activity::DSL::Linear::Sequence::IndexError: "I don't exist!" is not a valid step ID. Did you mean any of these ?/, op.inspect
185
+
186
+ error_message = %{#<Trailblazer::Activity::DSL::Linear::Sequence::IndexError: StepTest::InvalidStep:
187
+ \e[31m\"I don't exist!\" is not a valid step ID. Did you mean any of these ?\e[0m
188
+ \e[32m\"Start.default\"
189
+ \"End.success\"
190
+ \"End.pass_fast\"
191
+ \"End.fail_fast\"
192
+ \"End.failure\"\e[0m>}
193
+
194
+ assert_match error_message, op.inspect
182
195
  end
183
196
 
184
197
  #---
@@ -195,16 +208,16 @@ class StepTest < Minitest::Spec
195
208
 
196
209
  #---
197
210
  #- inheritance
198
- class New < Create
211
+ class New < Index
199
212
  end
200
213
 
201
- it { Trailblazer::Developer.railway(New).gsub(/0x.+?step_test.rb/, "").must_equal %{[>#<Proc::30 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c>,>d,>MyMacro]} }
214
+ it { Trailblazer::Developer.railway(New).must_equal %{[>my validate,>persist!,>I win!,>No, I do!]} }
202
215
 
203
- class Update < Create
204
- step :after_save!
216
+ class Update < Index
217
+ step :after_save
205
218
  end
206
219
 
207
- it { Trailblazer::Developer.railway(Update).gsub(/0x.+?step_test.rb/, "").must_equal %{[>#<Proc::30 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c>,>d,>MyMacro,>after_save!]} }
220
+ it { Trailblazer::Developer.railway(Update).must_equal %{[>my validate,>persist!,>I win!,>No, I do!,>after_save]} }
208
221
  end
209
222
 
210
223
  #---
data/test/trace_test.rb CHANGED
@@ -49,4 +49,28 @@ class TraceTest < Minitest::Spec
49
49
  |-- Create.task.params
50
50
  `-- End.success}
51
51
  end
52
+
53
+ it "Operation.wtf?" do
54
+ result = nil
55
+ output, = capture_io do
56
+ result = Create.wtf?(params: {x: 1}, a_return: true)
57
+ end
58
+
59
+ output.gsub(/0x\w+/, "").gsub(/@.+_test/, "").must_equal %{`-- TraceTest::Create
60
+ |-- \e[32mStart.default\e[0m
61
+ |-- \e[32mCreate.task.a\e[0m
62
+ |-- MyNested
63
+ | |-- \e[32mStart.default\e[0m
64
+ | |-- \e[32mB.task.b\e[0m
65
+ | |-- \e[32mB.task.e\e[0m
66
+ | `-- End.success
67
+ |-- \e[32mCreate.task.c\e[0m
68
+ |-- \e[32mCreate.task.params\e[0m
69
+ `-- End.success
70
+ }
71
+
72
+ result.success?.must_equal true
73
+ result[:a_return].must_equal true
74
+ result[:params].inspect.must_equal %{{:x=>1}}
75
+ end
52
76
  end
@@ -4,7 +4,7 @@ require 'trailblazer/operation/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "trailblazer-operation"
7
- spec.version = Trailblazer::Operation::VERSION
7
+ spec.version = Trailblazer::Version::Operation::VERSION
8
8
  spec.authors = ["Nick Sutterer"]
9
9
  spec.email = ["apotonick@gmail.com"]
10
10
  spec.description = %q(Trailblazer's operation object.)
@@ -17,14 +17,13 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_dependency "trailblazer-activity-dsl-linear", ">= 0.2.6", "< 1.0.0"
21
- spec.add_dependency "trailblazer-activity", ">= 0.10.0", "< 1.0.0"
22
- spec.add_dependency "trailblazer-developer", ">= 0.0.8"
20
+ spec.add_dependency "trailblazer-activity-dsl-linear", ">= 0.4.0", "< 1.0.0"
23
21
 
24
22
  spec.add_development_dependency "bundler"
25
23
  spec.add_development_dependency "minitest"
26
24
  spec.add_development_dependency "rake"
27
25
  spec.add_development_dependency "rubocop"
26
+ spec.add_development_dependency "trailblazer-developer"
28
27
 
29
28
  spec.required_ruby_version = ">= 2.1.0"
30
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trailblazer-operation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-20 00:00:00.000000000 Z
11
+ date: 2021-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: trailblazer-activity-dsl-linear
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.6
19
+ version: 0.4.0
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: 1.0.0
@@ -26,46 +26,26 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 0.2.6
29
+ version: 0.4.0
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: 1.0.0
33
33
  - !ruby/object:Gem::Dependency
34
- name: trailblazer-activity
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: 0.10.0
40
- - - "<"
41
- - !ruby/object:Gem::Version
42
- version: 1.0.0
43
- type: :runtime
44
- prerelease: false
45
- version_requirements: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 0.10.0
50
- - - "<"
51
- - !ruby/object:Gem::Version
52
- version: 1.0.0
53
- - !ruby/object:Gem::Dependency
54
- name: trailblazer-developer
34
+ name: bundler
55
35
  requirement: !ruby/object:Gem::Requirement
56
36
  requirements:
57
37
  - - ">="
58
38
  - !ruby/object:Gem::Version
59
- version: 0.0.8
60
- type: :runtime
39
+ version: '0'
40
+ type: :development
61
41
  prerelease: false
62
42
  version_requirements: !ruby/object:Gem::Requirement
63
43
  requirements:
64
44
  - - ">="
65
45
  - !ruby/object:Gem::Version
66
- version: 0.0.8
46
+ version: '0'
67
47
  - !ruby/object:Gem::Dependency
68
- name: bundler
48
+ name: minitest
69
49
  requirement: !ruby/object:Gem::Requirement
70
50
  requirements:
71
51
  - - ">="
@@ -79,7 +59,7 @@ dependencies:
79
59
  - !ruby/object:Gem::Version
80
60
  version: '0'
81
61
  - !ruby/object:Gem::Dependency
82
- name: minitest
62
+ name: rake
83
63
  requirement: !ruby/object:Gem::Requirement
84
64
  requirements:
85
65
  - - ">="
@@ -93,7 +73,7 @@ dependencies:
93
73
  - !ruby/object:Gem::Version
94
74
  version: '0'
95
75
  - !ruby/object:Gem::Dependency
96
- name: rake
76
+ name: rubocop
97
77
  requirement: !ruby/object:Gem::Requirement
98
78
  requirements:
99
79
  - - ">="
@@ -107,7 +87,7 @@ dependencies:
107
87
  - !ruby/object:Gem::Version
108
88
  version: '0'
109
89
  - !ruby/object:Gem::Dependency
110
- name: rubocop
90
+ name: trailblazer-developer
111
91
  requirement: !ruby/object:Gem::Requirement
112
92
  requirements:
113
93
  - - ">="
@@ -138,7 +118,6 @@ files:
138
118
  - lib/trailblazer/operation.rb
139
119
  - lib/trailblazer/operation/callable.rb
140
120
  - lib/trailblazer/operation/class_dependencies.rb
141
- - lib/trailblazer/operation/container.rb
142
121
  - lib/trailblazer/operation/deprecated_macro.rb
143
122
  - lib/trailblazer/operation/public_call.rb
144
123
  - lib/trailblazer/operation/railway.rb
@@ -155,7 +134,6 @@ files:
155
134
  - test/docs/macaroni_test.rb
156
135
  - test/docs/operation_test.rb
157
136
  - test/docs/wiring_test.rb
158
- - test/dry_container_test.rb
159
137
  - test/fast_track_test.rb
160
138
  - test/gemfiles/Gemfile.ruby-1.9
161
139
  - test/gemfiles/Gemfile.ruby-2.0
@@ -165,8 +143,6 @@ files:
165
143
  - test/introspect_test.rb
166
144
  - test/operation_test.rb
167
145
  - test/result_test.rb
168
- - test/ruby-2.0.0/operation_test.rb
169
- - test/ruby-2.0.0/step_test.rb
170
146
  - test/skill_test.rb
171
147
  - test/step_test.rb
172
148
  - test/test_helper.rb
@@ -208,7 +184,6 @@ test_files:
208
184
  - test/docs/macaroni_test.rb
209
185
  - test/docs/operation_test.rb
210
186
  - test/docs/wiring_test.rb
211
- - test/dry_container_test.rb
212
187
  - test/fast_track_test.rb
213
188
  - test/gemfiles/Gemfile.ruby-1.9
214
189
  - test/gemfiles/Gemfile.ruby-2.0
@@ -218,8 +193,6 @@ test_files:
218
193
  - test/introspect_test.rb
219
194
  - test/operation_test.rb
220
195
  - test/result_test.rb
221
- - test/ruby-2.0.0/operation_test.rb
222
- - test/ruby-2.0.0/step_test.rb
223
196
  - test/skill_test.rb
224
197
  - test/step_test.rb
225
198
  - test/test_helper.rb
@@ -1,14 +0,0 @@
1
- module Trailblazer
2
- module Operation::Container
3
- def options_for_public_call(options={}, *containers)
4
- # generate the skill hash that embraces runtime options plus potential containers, the so called Runtime options.
5
- # This wrapping is supposed to happen once in the entire system.
6
-
7
- hash_transformer = ->(containers) { containers[0].to_hash } # FIXME: don't transform any containers into kw args.
8
-
9
- immutable_options = Trailblazer::Context::ContainerChain.new([options, *containers], to_hash: hash_transformer)
10
-
11
- Trailblazer::Context(immutable_options)
12
- end
13
- end
14
- end
@@ -1,25 +0,0 @@
1
- require "test_helper"
2
- require "dry/container"
3
-
4
- class DryContainerTest < Minitest::Spec
5
- my_container = Dry::Container.new
6
- my_container.register("user_repository", -> { Object })
7
- my_container.namespace("contract") do
8
- register("create") { Array }
9
- end
10
-
11
- class Create < Trailblazer::Operation
12
- extend Trailblazer::Operation::Container
13
- end
14
-
15
- it "allows 2.2 call style" do
16
- Create.({}, my_container)["user_repository"].must_equal Object
17
- end
18
-
19
- it { Create.({}, {}, my_container)["user_repository"].must_equal Object }
20
- it { Create.({}, {}, my_container)["contract.create"].must_equal Array }
21
- # also allows our own options PLUS containers.
22
- it { Create.({}, {"model" => String}, my_container)["model"].must_equal String }
23
- it { Create.({}, {"model" => String}, my_container)["user_repository"].must_equal Object }
24
- it { Create.({}, {"user_repository" => Integer}, my_container)["user_repository"].must_equal Integer }
25
- end
@@ -1,61 +0,0 @@
1
- require "test_helper"
2
-
3
- class DeclarativeApiTest < Minitest::Spec
4
- #---
5
- #- step, pass, fail
6
-
7
- # Test: step/pass/fail
8
- # * do they deviate properly?
9
- class Create < Trailblazer::Operation
10
- step :decide!
11
- success :wasnt_ok!
12
- success :was_ok!
13
- failure :return_true!
14
- failure :return_false!
15
-
16
- def decide!(options, decide: raise, **_o)
17
- options["a"] = true
18
- decide
19
- end
20
-
21
- def wasnt_ok!(options, **_o)
22
- options["y"] = false
23
- end
24
-
25
- def was_ok!(options, **_o)
26
- options["x"] = true
27
- end
28
-
29
- def return_true!(options, **_o); options["b"] = true end
30
-
31
- def return_false!(options, **_o); options["c"] = false end
32
- end
33
-
34
- it { Create.({}, decide: true).inspect("a", "x", "y", "b", "c").must_equal %{<Result:true [true, true, false, nil, nil] >} }
35
- it { Create.({}, decide: false).inspect("a", "x", "y", "b", "c").must_equal %{<Result:false [true, nil, nil, true, false] >} }
36
-
37
- #---
38
- #- trace
39
-
40
- it do
41
- end
42
-
43
- #---
44
- #- empty class
45
- class Noop < Trailblazer::Operation
46
- end
47
-
48
- it { Noop.().inspect("params").must_equal %{<Result:true [{}] >} }
49
-
50
- #---
51
- #- pass
52
- #- fail
53
- class Update < Trailblazer::Operation
54
- pass ->(options, **_o) { options["a"] = false }
55
- step ->(options, params: raise, **_o) { options["b"] = params[:decide] }
56
- fail ->(options, **_o) { options["c"] = true }
57
- end
58
-
59
- it { Update.(decide: true).inspect("a", "b", "c").must_equal %{<Result:true [false, true, nil] >} }
60
- it { Update.(decide: false).inspect("a", "b", "c").must_equal %{<Result:false [false, false, true] >} }
61
- end
@@ -1,137 +0,0 @@
1
- require "test_helper"
2
-
3
- # Tests
4
- # --- step ->(*o) { snippet }
5
- # --- step Callable
6
- # --- step :method
7
- # --- step MyMacro
8
- class StepTest < Minitest::Spec
9
- class Callable
10
- def self.call(options, b: nil, **_o)
11
- options["b"] = b
12
- end
13
- end
14
-
15
- module Implementation
16
- module_function
17
-
18
- def c(options, c: nil, **_o)
19
- options["c"] = c
20
- end
21
- end
22
-
23
- MyMacro = ->(direction, options, flow_options) do
24
- options["e"] = options[:e]
25
-
26
- [direction, options, flow_options]
27
- end
28
-
29
- class Create < Trailblazer::Operation
30
- step ->(options, a: nil, **_o) { options["a"] = a }
31
- step Callable
32
- step Implementation.method(:c)
33
- step :d
34
- step [MyMacro, {}] # doesn't provide runner_options.
35
-
36
- def d(options, d: nil, **_o)
37
- options["d"] = d
38
- end
39
- end
40
-
41
- it { Create.({}, a: 1, b: 2, c: 3, d: 4, e: 5).inspect("a", "b", "c", "d", "e").must_equal "<Result:true [1, 2, 3, 4, 5] >" }
42
-
43
- it { Trailblazer::Operation::Inspect.(Create).gsub(/0x.+?step_test.rb/, "").must_equal %{[>#<Proc::29 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c>,>d,>[#<Proc::22 (lambda)>, {}]]} }
44
- # poor test to make sure we pass debug information to Activity.
45
- it { Create["__activity__"].graph.find_all(:d).first[:id].must_equal :d }
46
-
47
- #---
48
- #- :before, :after, :replace, :delete, :override
49
- class A < Trailblazer::Operation
50
- step :a!
51
- def a!(options, **_o); options["a"] = 1; end
52
- def a!(options, **_o); options["a"] = 1; end if RUBY_VERSION == "2.0.0"
53
- end
54
-
55
- class B < A
56
- step :b!, before: :a!
57
- step :c!, before: :a!
58
- step :d!, after: :b!
59
- end
60
-
61
- it { Trailblazer::Operation::Inspect.(B).must_equal %{[>b!,>d!,>c!,>a!]} }
62
-
63
- class C < B
64
- step :e!, replace: :c!
65
- step nil, delete: :d!
66
- end
67
-
68
- it { Trailblazer::Operation::Inspect.(C).must_equal %{[>b!,>e!,>a!]} }
69
-
70
- class D < Trailblazer::Operation
71
- step :a!
72
- step :b!
73
- step :b!, override: true
74
- end
75
-
76
- it { Trailblazer::Operation::Inspect.(D).must_equal %{[>a!,>b!]} }
77
-
78
- # not existent :name
79
- it do
80
- err = assert_raises Trailblazer::Operation::Railway::Sequence::IndexError do
81
- class E < Trailblazer::Operation
82
- step :a, before: "I don't exist!"
83
- end
84
- end
85
-
86
- err.inspect.must_equal "#<Trailblazer::Operation::Railway::Sequence::IndexError: I don't exist!>"
87
- end
88
-
89
- #---
90
- #- :name
91
- #- step :whatever, name: :validate
92
- class Index < Trailblazer::Operation
93
- step :validate!, name: "my validate"
94
- step :persist!
95
- step [MyMacro, name: "I win!"]
96
- step [MyMacro, name: "I win!"], name: "No, I do!"
97
- end
98
-
99
- it { Trailblazer::Operation::Inspect.(Index).must_equal %{[>my validate,>persist!,>I win!,>No, I do!]} }
100
-
101
- #---
102
- #- inheritance
103
- class New < Create
104
- end
105
-
106
- it { Trailblazer::Operation::Inspect.(New).gsub(/0x.+?step_test.rb/, "").must_equal %{[>#<Proc::29 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c>,>d,>[#<Proc::22 (lambda)>, {}]]} }
107
-
108
- class Update < Create
109
- step :after_save!
110
- end
111
-
112
- it { Trailblazer::Operation::Inspect.(Update).gsub(/0x.+?step_test.rb/, "").must_equal %{[>#<Proc::29 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c>,>d,>[#<Proc::22 (lambda)>, {}],>after_save!]} }
113
- end
114
-
115
- #---
116
- #- Macros with the old `input` arg.
117
- # step [ ->(input, options) { } ]
118
- # TODO: remove me in 2.2.
119
- class StepWithDeprecatedMacroTest < Minitest::Spec
120
- class Create < Trailblazer::Operation
121
- MyOutdatedMacro = ->(input, options) {
122
- options["x"] = input.class
123
- }
124
-
125
- class AnotherOldMacro
126
- def self.call(input, options)
127
- options["y"] = input.class
128
- end
129
- end
130
-
131
- step [MyOutdatedMacro, name: :outdated]
132
- step [AnotherOldMacro, name: :oldie]
133
- end
134
-
135
- it { Trailblazer::Operation::Inspect.(Create).gsub(/0x.+?step_test.rb/, "").must_equal %{[>outdated,>oldie]} }
136
- it { Create.().inspect("x", "y").must_equal %{<Result:true [StepWithDeprecatedMacroTest::Create, StepWithDeprecatedMacroTest::Create] >} }
137
- end