DEV: Fix policy classes delegating their `#call` method in services
There’s currently a bug when using a dedicated class as a policy in services: if that class delegates its `#call` method (to an underlying strategy object for example), then an error will be raised saying steps aren’t allowed to provide default parameters. This should not happen, and this patch fixes that issue.
This commit is contained in:
parent
9812407f76
commit
133a648d9b
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue