diff --git a/lib/convenient_service/configs/standard.rb b/lib/convenient_service/configs/standard.rb index bad900e65e2..5b50bcd1718 100644 --- a/lib/convenient_service/configs/standard.rb +++ b/lib/convenient_service/configs/standard.rb @@ -86,11 +86,13 @@ class self::Result use Plugins::Result::CanRecalculateResult::Concern use Plugins::Result::HasStep::Concern + use Plugins::Result::CanBeTried::Concern use Plugins::Result::CanHaveParentResult::Concern end middlewares :initialize do use Plugins::Result::HasStep::Initialize::Middleware + use Plugins::Result::CanBeTried::Initialize::Middleware use Plugins::Result::CanHaveParentResult::Initialize::Middleware end @@ -132,6 +134,7 @@ class self::Result middlewares :to_kwargs do use Plugins::Result::HasStep::ToKwargs::Middleware + use Plugins::Result::CanBeTried::ToKwargs::Middleware use Plugins::Result::CanHaveParentResult::ToKwargs::Middleware end end diff --git a/lib/convenient_service/service/plugins/can_have_try_result/middleware.rb b/lib/convenient_service/service/plugins/can_have_try_result/middleware.rb index 7ec3a185d7b..fc247faac31 100644 --- a/lib/convenient_service/service/plugins/can_have_try_result/middleware.rb +++ b/lib/convenient_service/service/plugins/can_have_try_result/middleware.rb @@ -23,7 +23,7 @@ def next(...) raise Errors::ServiceTryReturnValueNotKindOfResult.new(service: entity, result: try_result) unless commands.is_result?(try_result) raise Errors::ServiceTryReturnValueNotSuccess.new(service: entity, result: try_result) unless try_result.success? - try_result.copy + try_result.copy(overrides: {kwargs: {try_result: true}}) end end end diff --git a/lib/convenient_service/service/plugins/has_result/entities/result/plugins.rb b/lib/convenient_service/service/plugins/has_result/entities/result/plugins.rb index eddcc0dbca8..c39c8262730 100644 --- a/lib/convenient_service/service/plugins/has_result/entities/result/plugins.rb +++ b/lib/convenient_service/service/plugins/has_result/entities/result/plugins.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require_relative "plugins/can_recalculate_result" +require_relative "plugins/can_be_tried" require_relative "plugins/has_j_send_status_and_attributes" require_relative "plugins/has_inspect" require_relative "plugins/has_step" diff --git a/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried.rb b/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried.rb new file mode 100644 index 00000000000..355591d1fa3 --- /dev/null +++ b/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +require_relative "can_be_tried/concern" +require_relative "can_be_tried/initialize" +require_relative "can_be_tried/to_kwargs" diff --git a/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/concern.rb b/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/concern.rb new file mode 100644 index 00000000000..61529a79bc5 --- /dev/null +++ b/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/concern.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module ConvenientService + module Service + module Plugins + module HasResult + module Entities + class Result + module Plugins + module CanBeTried + module Concern + include Support::Concern + + instance_methods do + ## + # @return [Boolean] + # + def try_result? + Utils.to_bool(internals.cache[:try_result]) + end + end + end + end + end + end + end + end + end + end +end diff --git a/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/initialize.rb b/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/initialize.rb new file mode 100644 index 00000000000..1442acbf304 --- /dev/null +++ b/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/initialize.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require_relative "initialize/middleware" diff --git a/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/initialize/middleware.rb b/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/initialize/middleware.rb new file mode 100644 index 00000000000..c3c3c7f1fd7 --- /dev/null +++ b/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/initialize/middleware.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module ConvenientService + module Service + module Plugins + module HasResult + module Entities + class Result + module Plugins + module CanBeTried + module Initialize + class Middleware < MethodChainMiddleware + intended_for :initialize, entity: :result + + ## + # @param args [Array] + # @param kwargs [Hash{Symbol => Object}] + # @param block [Proc, nil] + # @return [void] + # + def next(*args, **kwargs, &block) + entity.internals.cache[:try_result] = kwargs[:try_result] + + chain.next(*args, **kwargs, &block) + end + end + end + end + end + end + end + end + end + end +end diff --git a/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/to_kwargs.rb b/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/to_kwargs.rb new file mode 100644 index 00000000000..c7a94156f44 --- /dev/null +++ b/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/to_kwargs.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require_relative "to_kwargs/middleware" diff --git a/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/to_kwargs/middleware.rb b/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/to_kwargs/middleware.rb new file mode 100644 index 00000000000..e0eb22e4754 --- /dev/null +++ b/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/to_kwargs/middleware.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module ConvenientService + module Service + module Plugins + module HasResult + module Entities + class Result + module Plugins + module CanBeTried + module ToKwargs + class Middleware < MethodChainMiddleware + intended_for :to_kwargs, entity: :result + + ## + # @return [Hash{Symbol => Object}] + # + def next(...) + chain.next(...).merge(try_result: entity.try_result?) + end + end + end + end + end + end + end + end + end + end +end diff --git a/spec/lib/convenient_service/configs/standard_spec.rb b/spec/lib/convenient_service/configs/standard_spec.rb index 973135176d7..2deaac31d6d 100644 --- a/spec/lib/convenient_service/configs/standard_spec.rb +++ b/spec/lib/convenient_service/configs/standard_spec.rb @@ -206,6 +206,7 @@ ConvenientService::Common::Plugins::HasResultDuckShortSyntax::Concern, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanRecalculateResult::Concern, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasStep::Concern, + ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanBeTried::Concern, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanHaveParentResult::Concern ] end @@ -221,6 +222,7 @@ ConvenientService::Common::Plugins::NormalizesEnv::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasJSendStatusAndAttributes::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasStep::Initialize::Middleware, + ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanBeTried::Initialize::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanHaveParentResult::Initialize::Middleware ] end @@ -352,6 +354,7 @@ [ ConvenientService::Common::Plugins::NormalizesEnv::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasStep::ToKwargs::Middleware, + ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanBeTried::ToKwargs::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanHaveParentResult::ToKwargs::Middleware ] end diff --git a/spec/lib/convenient_service/examples/dry/gemfile/dry_service/config_spec.rb b/spec/lib/convenient_service/examples/dry/gemfile/dry_service/config_spec.rb index c5ebc130b82..385984a7596 100644 --- a/spec/lib/convenient_service/examples/dry/gemfile/dry_service/config_spec.rb +++ b/spec/lib/convenient_service/examples/dry/gemfile/dry_service/config_spec.rb @@ -210,6 +210,7 @@ ConvenientService::Common::Plugins::HasResultDuckShortSyntax::Concern, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanRecalculateResult::Concern, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasStep::Concern, + ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanBeTried::Concern, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanHaveParentResult::Concern ] end @@ -225,6 +226,7 @@ ConvenientService::Common::Plugins::NormalizesEnv::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasJSendStatusAndAttributes::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasStep::Initialize::Middleware, + ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanBeTried::Initialize::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanHaveParentResult::Initialize::Middleware ] end @@ -356,6 +358,7 @@ [ ConvenientService::Common::Plugins::NormalizesEnv::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasStep::ToKwargs::Middleware, + ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanBeTried::ToKwargs::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanHaveParentResult::ToKwargs::Middleware ] end diff --git a/spec/lib/convenient_service/examples/rails/gemfile/rails_service/config_spec.rb b/spec/lib/convenient_service/examples/rails/gemfile/rails_service/config_spec.rb index 20612652d85..54dc126d4c5 100644 --- a/spec/lib/convenient_service/examples/rails/gemfile/rails_service/config_spec.rb +++ b/spec/lib/convenient_service/examples/rails/gemfile/rails_service/config_spec.rb @@ -212,6 +212,7 @@ ConvenientService::Common::Plugins::HasResultDuckShortSyntax::Concern, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanRecalculateResult::Concern, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasStep::Concern, + ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanBeTried::Concern, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanHaveParentResult::Concern ] end @@ -227,6 +228,7 @@ ConvenientService::Common::Plugins::NormalizesEnv::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasJSendStatusAndAttributes::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasStep::Initialize::Middleware, + ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanBeTried::Initialize::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanHaveParentResult::Initialize::Middleware ] end @@ -358,6 +360,7 @@ [ ConvenientService::Common::Plugins::NormalizesEnv::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasStep::ToKwargs::Middleware, + ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanBeTried::ToKwargs::Middleware, ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanHaveParentResult::ToKwargs::Middleware ] end diff --git a/spec/lib/convenient_service/service/plugins/can_have_try_result/middleware_spec.rb b/spec/lib/convenient_service/service/plugins/can_have_try_result/middleware_spec.rb index 11f3eac409b..f770d71f839 100644 --- a/spec/lib/convenient_service/service/plugins/can_have_try_result/middleware_spec.rb +++ b/spec/lib/convenient_service/service/plugins/can_have_try_result/middleware_spec.rb @@ -168,7 +168,7 @@ def try_result specify do expect { method_value } .to delegate_to(try_result, :copy) - .without_arguments + .with_arguments(overrides: {kwargs: {try_result: true}}) .and_return_its_value end end diff --git a/spec/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/concern_spec.rb b/spec/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/concern_spec.rb new file mode 100644 index 00000000000..2563c097784 --- /dev/null +++ b/spec/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/concern_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require "spec_helper" + +require "convenient_service" + +# rubocop:disable RSpec/NestedGroups, RSpec/MultipleMemoizedHelpers +RSpec.describe ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanBeTried::Concern do + include ConvenientService::RSpec::Matchers::CacheItsValue + + example_group "modules" do + include ConvenientService::RSpec::Matchers::IncludeModule + + subject { described_class } + + it { is_expected.to include_module(ConvenientService::Support::Concern) } + + context "when included" do + subject { result_class } + + let(:result_class) do + Class.new.tap do |klass| + klass.class_exec(described_class) do |mod| + include mod + end + end + end + + it { is_expected.to include_module(described_class::InstanceMethods) } + end + end + + example_group "instance methods" do + describe "#try_result?" do + let(:result) { service.result } + + let(:service) do + Class.new do + include ConvenientService::Configs::Standard + + def result + success + end + + def try_result + success + end + end + end + + context "when result is NOT from `try_result` method" do + let(:result) { service.result } + + it "returns `false`" do + expect(result.try_result?).to eq(false) + end + end + + context "when result is from `try_result` method" do + let(:result) { service.try_result } + + it "returns `true`" do + expect(result.try_result?).to eq(true) + end + end + end + end +end +# rubocop:enable RSpec/NestedGroups, RSpec/MultipleMemoizedHelpers diff --git a/spec/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/initialize/middleware_spec.rb b/spec/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/initialize/middleware_spec.rb new file mode 100644 index 00000000000..b79623cb8d7 --- /dev/null +++ b/spec/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/initialize/middleware_spec.rb @@ -0,0 +1,100 @@ +# frozen_string_literal: true + +require "spec_helper" + +require "convenient_service" + +# rubocop:disable RSpec/NestedGroups, RSpec/MultipleMemoizedHelpers +RSpec.describe ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanBeTried::Initialize::Middleware do + let(:middleware) { described_class } + + example_group "inheritance" do + include ConvenientService::RSpec::Matchers::BeDescendantOf + + subject { middleware } + + it { is_expected.to be_descendant_of(ConvenientService::MethodChainMiddleware) } + end + + example_group "class methods" do + describe ".intended_methods" do + let(:spec) do + Class.new(ConvenientService::MethodChainMiddleware) do + intended_for :initialize, entity: :result + end + end + + it "returns intended methods" do + expect(middleware.intended_methods).to eq(spec.intended_methods) + end + end + end + + example_group "instance methods" do + describe "#call" do + include ConvenientService::RSpec::Helpers::WrapMethod + include ConvenientService::RSpec::Matchers::CallChainNext + include ConvenientService::RSpec::Matchers::DelegateTo + + subject(:method_value) { method.call(**attributes) } + + let(:method) { wrap_method(result, :initialize, observe_middleware: middleware) } + + let(:service) do + Class.new.tap do |klass| + klass.class_exec(middleware) do |middleware| + include ConvenientService::Configs::Standard + + self::Result.class_exec(middleware) do |middleware| + middlewares :initialize do + observe middleware + end + end + + def result + success + end + end + end + end + + let(:result) { service.result } + + context "when `try_result` is NOT passed" do + let(:attributes) { result.jsend_attributes.to_h } + + specify do + expect { method_value } + .to delegate_to(result.internals.cache, :write) + .with_arguments(:try_result, nil) + end + + specify do + expect { method_value } + .to call_chain_next.on(method) + .with_arguments(**attributes) + .and_return_its_value + end + end + + context "when `try_result` is passed" do + let(:attributes) { result.jsend_attributes.to_h.merge(try_result: try_result) } + let(:try_result) { true } + + specify do + expect { method_value } + .to delegate_to(result.internals.cache, :write) + .with_arguments(:try_result, try_result) + end + + specify do + expect { method_value } + .to call_chain_next.on(method) + .with_arguments(**attributes) + .and_return_its_value + end + end + end + end +end +# rubocop:enable RSpec/NestedGroups, RSpec/MultipleMemoizedHelpers diff --git a/spec/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/to_kwargs/middleware_spec.rb b/spec/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/to_kwargs/middleware_spec.rb new file mode 100644 index 00000000000..775012d449d --- /dev/null +++ b/spec/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_tried/to_kwargs/middleware_spec.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require "spec_helper" + +require "convenient_service" + +# rubocop:disable RSpec/NestedGroups, RSpec/MultipleMemoizedHelpers +RSpec.describe ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::CanBeTried::ToKwargs::Middleware do + let(:middleware) { described_class } + + example_group "inheritance" do + include ConvenientService::RSpec::Matchers::BeDescendantOf + + subject { described_class } + + it { is_expected.to be_descendant_of(ConvenientService::MethodChainMiddleware) } + end + + example_group "class methods" do + describe ".intended_methods" do + let(:spec) do + Class.new(ConvenientService::MethodChainMiddleware) do + intended_for :to_kwargs, entity: :result + end + end + + it "returns intended methods" do + expect(described_class.intended_methods).to eq(spec.intended_methods) + end + end + end + + example_group "instance methods" do + describe "#call" do + include ConvenientService::RSpec::Helpers::WrapMethod + include ConvenientService::RSpec::Matchers::CallChainNext + + subject(:method_value) { method.call } + + let(:method) { wrap_method(result, :to_kwargs, observe_middleware: middleware) } + + let(:service) do + Class.new.tap do |klass| + klass.class_exec(middleware) do |middleware| + include ConvenientService::Configs::Standard + + self::Result.class_exec(middleware) do |middleware| + middlewares :to_kwargs do + observe middleware + end + end + + def result + success + end + end + end + end + + let(:result) { service.result } + + specify do + expect { method_value }.to call_chain_next.on(method) + end + + it "merges `try_result` to kwargs" do + expect(method_value[:try_result]).to eq(result.try_result?) + end + end + end +end +# rubocop:enable RSpec/NestedGroups, RSpec/MultipleMemoizedHelpers diff --git a/spec/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_try_result_spec.rb b/spec/lib/convenient_service/service/plugins/has_result/entities/result/plugins/can_be_try_result_spec.rb new file mode 100644 index 00000000000..e69de29bb2d