diff --git a/lib/service/base.rb b/lib/service/base.rb index bde43a0f9aa..ecf1537be65 100644 --- a/lib/service/base.rb +++ b/lib/service/base.rb @@ -91,21 +91,17 @@ module Service # @!visibility private module StepsHelpers def model(name = :model, step_name = :"fetch_#{name}", optional: false) - steps << ModelStep.new(name, step_name, optional: optional) + steps << ModelStep.new(name, step_name, optional:) end def params(name = :default, default_values_from: nil, &block) contract_class = Class.new(Service::ContractBase).tap { _1.class_eval(&block) } const_set("#{name.to_s.classify.sub("Default", "")}Contract", contract_class) - steps << ContractStep.new( - name, - class_name: contract_class, - default_values_from: default_values_from, - ) + steps << ContractStep.new(name, class_name: contract_class, default_values_from:) end def policy(name = :default, class_name: nil) - steps << PolicyStep.new(name, class_name: class_name) + steps << PolicyStep.new(name, class_name:) end def step(name) @@ -152,7 +148,7 @@ module Service def run_step object = class_name&.new(context) method = object&.method(:call) || instance.method(method_name) - if method.parameters.any? { _1[0] != :keyreq } + if !object && method.parameters.any? { _1[0] != :keyreq } raise "In #{type} '#{name}': default values in step implementations are not allowed. Maybe they could be defined in a params or options block?" end args = context.slice(*method.parameters.select { _1[0] == :keyreq }.map(&:last)) diff --git a/spec/lib/service_spec.rb b/spec/lib/service_spec.rb index 18575c8876a..37c1ee5d176 100644 --- a/spec/lib/service_spec.rb +++ b/spec/lib/service_spec.rb @@ -38,6 +38,36 @@ RSpec.describe Service do expect { service_class.call }.to raise_error(/In policy 'my_policy': default values/) end end + + context "when providing a class which delegates its `#call` method" do + before do + service_class.class_eval do + class MyPolicy < Service::PolicyBase + class MyStrategy + def call + end + + def reason + end + end + + attr_reader :strategy + + delegate :call, :reason, to: :strategy + + def initialize(*) + @strategy = MyStrategy.new + end + end + + policy :my_policy, class_name: MyPolicy + end + end + + it "does not raise an error" do + expect { service_class.call }.not_to raise_error + end + end end describe "Generic step" do