From 193700b9719531a0b54b7adc200eedc8714e300f Mon Sep 17 00:00:00 2001 From: Arkadiy Zabazhanov Date: Wed, 25 Sep 2024 10:41:58 +0700 Subject: [PATCH] Add `component` convenience method --- lib/operations/convenience.rb | 23 ++++++++++++----------- spec/operations/convenience_spec.rb | 29 +++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/lib/operations/convenience.rb b/lib/operations/convenience.rb index 74481c5..400bb66 100644 --- a/lib/operations/convenience.rb +++ b/lib/operations/convenience.rb @@ -83,20 +83,21 @@ def contract(prefix = nil, from: OperationContract, &block) const_set(:"#{prefix.to_s.camelize}Contract", contract) end - %w[policy precondition callback].each do |kind| - define_method kind do |prefix = nil, from: Object, &block| - raise ArgumentError.new("Please provide either a superclass or a block for #{kind}") unless from || block - - klass = Class.new(from) + def component(name, from: Object, dry_initializer: false, dry_monads_result: false, &block) # rubocop:disable Metrics/CyclomaticComplexity + raise ArgumentError.new("Please provide either a superclass or a block for #{name}") unless from || block - if from == Object - klass.extend(Dry::Initializer) - klass.include(Dry::Monads[:result]) - end + klass = Class.new(from) + klass.extend(Dry::Initializer) if dry_initializer && !klass.include?(Dry::Initializer) # rubocop:disable Rails/NegateInclude + klass.include(Dry::Monads[:result]) if dry_monads_result && !klass.is_a?(Dry::Monads[:result]) + klass.define_method(:call, &block) if block - klass.define_method(:call, &block) if block + const_set(name.to_s.camelize, klass) + end - const_set(:"#{prefix.to_s.camelize}#{kind.camelize}", klass) + %w[policy precondition callback].each do |kind| + define_method kind do |prefix = nil, from: Object, &block| + component([prefix, kind].compact_blank.join("_"), from: from, + dry_initializer: true, dry_monads_result: true, &block) end end end diff --git a/spec/operations/convenience_spec.rb b/spec/operations/convenience_spec.rb index 6f99e63..0f80611 100644 --- a/spec/operations/convenience_spec.rb +++ b/spec/operations/convenience_spec.rb @@ -66,12 +66,39 @@ def self.default(arg) end end + describe "#component" do + subject(:component) { dummy_operation.component(name, **options) { :foobar } } + + let(:name) { :custom_hydrator } + let(:options) { {} } + + specify do + expect(component.name).to eq("DummyOperation::CustomHydrator") + expect(component).not_to be_a(Dry::Initializer) + expect(component).not_to include(Dry::Monads[:result]) + expect(component.new.call).to eq(:foobar) + end + + context "with options given" do + let(:options) { { dry_initializer: true, dry_monads_result: true } } + + specify do + expect(component.name).to eq("DummyOperation::CustomHydrator") + expect(component).to be_a(Dry::Initializer) + expect(component).to include(Dry::Monads[:result]) + expect(component.new.call).to eq(:foobar) + end + end + end + %w[policy precondition callback].each do |kind| describe "##{kind}" do subject(:component) { dummy_operation.public_send(kind) { :foobar } } specify do expect(component.name).to eq("DummyOperation::#{kind.camelize}") + expect(component).to be_a(Dry::Initializer) + expect(component).to include(Dry::Monads[:result]) expect(component.new.call).to eq(:foobar) end @@ -89,6 +116,8 @@ def other_method specify do expect(component.name).to eq("DummyOperation::#{kind.camelize}") expect(component).to be < parent + expect(component).to be_a(Dry::Initializer) + expect(component).to include(Dry::Monads[:result]) expect(component.new.call).to eq(:foobar) end end