From ac2fa2b667674032c38b68e37860cbad54e865ab Mon Sep 17 00:00:00 2001 From: Nick Sutterer Date: Mon, 27 Nov 2023 14:55:10 +0100 Subject: [PATCH] add `Operation.call_with_public_interface_from_call` as an entry point for normalizing arguments of `Operation.call` (public style). --- lib/trailblazer/operation/public_call.rb | 24 +++++++++++++++++------- test/operation_test.rb | 10 +++++++++- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/trailblazer/operation/public_call.rb b/lib/trailblazer/operation/public_call.rb index 5b2e840..d866849 100644 --- a/lib/trailblazer/operation/public_call.rb +++ b/lib/trailblazer/operation/public_call.rb @@ -16,7 +16,16 @@ module Operation::PublicCall def call(options = {}, flow_options = {}, **circuit_options) 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 thing as we're fading out Operation::public_call anyway. - call_with_public_interface(options, flow_options, **circuit_options) + call_with_public_interface_from_call(options, flow_options, **circuit_options) + end + + # @private Please do not override this method as it might get removed. + def call_with_public_interface_from_call(options, flow_options, **circuit_options) + # normalize options. + options = options + .merge(circuit_options) # when using Op.call(params:, ...), {circuit_options} will always be ctx variables. + + call_with_public_interface(options, flow_options) end # Default {@activity} call interface which doesn't accept {circuit_options} @@ -25,23 +34,24 @@ def call(options = {}, flow_options = {}, **circuit_options) # # @return [Operation::Railway::Result] # - # @private - + # @semi-public It's OK to override this method. def call_with_public_interface(options, flow_options, invoke_class: Activity::TaskWrap, **circuit_options) flow_options = flow_options_for_public_call(flow_options) # In Ruby < 3, calling Op.(params: {}, "current_user" => user) results in both {circuit_options} and {options} containing variables. # In Ruby 3.0, **circuit_options is always empty. - options = circuit_options.any? ? circuit_options.merge(options) : options + # options = circuit_options.any? ? circuit_options.merge(options) : options ctx = options_for_public_call(options, flow_options) - # call the activity. - # This will result in invoking {::call_with_circuit_interface}. + # Call the activity as it if was a step in an endpoint. + + # This will result in invoking {self.call_with_circuit_interface}. signal, (ctx, flow_options) = invoke_class.invoke( self, [ctx, flow_options], - container_activity: Activity::TaskWrap.container_activity_for(self, wrap_static: initial_wrap_static) # we cannot make this static because of {self} unless we override {#inherited}. + container_activity: Activity::TaskWrap.container_activity_for(self, wrap_static: initial_wrap_static), # we cannot make this static because of {self} unless we override {#inherited}. + **circuit_options ) # Result is successful if the activity ended with an End event derived from Railway::End::Success. diff --git a/test/operation_test.rb b/test/operation_test.rb index 1e06a40..a5a1b72 100644 --- a/test/operation_test.rb +++ b/test/operation_test.rb @@ -21,7 +21,14 @@ def self.capture_circuit_options((ctx, flow_options), **circuit_options) it "doesn't mistake circuit options as ctx variables when using the call interface" do result = Noop.call(params: {}, model: true, "current_user" => Object) # call with public interface. #@ {:variable_for_circuit_options} is not supposed to be in {ctx}. - assert_equal result.inspect, %({}, :model=>true, "current_user"=>Object} mutable_options={:capture_circuit_options=>"[:exec_context, :wrap_runtime, :activity, :runner]"}> >) + assert_equal result.inspect, %({}, :model=>true, "current_user"=>Object} mutable_options={:capture_circuit_options=>"[:wrap_runtime, :activity, :exec_context, :runner]"}> >) + end + +#@ {#call_with_public_interface} + it "doesn't mistake circuit options as ctx variables when using circuit-interface" do + result = Noop.call_with_public_interface({params: {}}, {}, variable_for_circuit_options: true) # call_with_public_interface has two positional args, and kwargs for {circuit_options}. + + assert_equal result.inspect, %({}} mutable_options={:capture_circuit_options=>\"[:variable_for_circuit_options, :wrap_runtime, :activity, :exec_context, :runner]\"}> >) end end @@ -171,6 +178,7 @@ class Collect < Trailblazer::Operation ctx.inspect.must_equal %{#{:decide=>true}} mutable_options={\"a\"=>false, \"b\"=>true}>} # Call by passing aliases as an argument. + # This uses {#call}'s second positional argument. if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0.0") result = Update.( options,