diff --git a/lib/dry/transaction/instance_methods.rb b/lib/dry/transaction/instance_methods.rb index e271f32..23aeb88 100644 --- a/lib/dry/transaction/instance_methods.rb +++ b/lib/dry/transaction/instance_methods.rb @@ -12,7 +12,7 @@ module InstanceMethods attr_reader :listeners attr_reader :stack - def initialize(steps: (self.class.steps), listeners: nil, **operations) + def initialize(*args, steps: (self.class.steps), listeners: nil, **operations) @steps = steps.map { |step| operation = resolve_operation(step, operations) step.with(operation: operation) @@ -20,6 +20,32 @@ def initialize(steps: (self.class.steps), listeners: nil, **operations) @operations = operations @stack = Stack.new(@steps) subscribe(listeners) unless listeners.nil? + + next_super_method = method(__method__).super_method + super_initialize = nil + + loop do + if next_super_method.owner.name =~ /Dry::Transaction/ + next_super_method = next_super_method.super_method + else + super_initialize = next_super_method + break + end + end + + if super_initialize && super_initialize.parameters.empty? + super() + elsif super_initialize + super_kwarg_names = super_initialize.parameters.each_with_object([]) { |(type, name), names| + names << name if [:key, :keyreq].include?(type) + } + + super_kwargs = operations.each_with_object({}) { |(key, val), kwargs| + kwargs[key] = val if super_kwarg_names.include?(key) + } + + super(*args, **super_kwargs) + end end def call(input = nil, &block) diff --git a/spec/integration/user_class_hierarchy_spec.rb b/spec/integration/user_class_hierarchy_spec.rb new file mode 100644 index 0000000..33877a5 --- /dev/null +++ b/spec/integration/user_class_hierarchy_spec.rb @@ -0,0 +1,25 @@ +RSpec.describe "dry transaction used with inheriting user classes" do + let(:base_class) do + Class.new do + attr_reader :base_called + + def initialize(*_args) + @base_called = true + end + end + end + + let(:child_class) do + Class.new(base_class) do + include Dry::Transaction + end + end + + context "when user class inherits from another class" do + subject { child_class.new } + + it "calls base class initializer" do + expect(subject.base_called).to be true + end + end +end