diff --git a/lib/active_interaction/base.rb b/lib/active_interaction/base.rb index ca7b9a34..dfb1ddb9 100644 --- a/lib/active_interaction/base.rb +++ b/lib/active_interaction/base.rb @@ -109,6 +109,23 @@ def add_filter(klass, name, options, &block) initialize_filter(klass.new(name, options, &block)) end + # @since 2.0.0 + def proxy(name, inputs) + (@_proxies ||= Set.new).add(name) + + attr_reader name + + inputs.each do |input| + define_method(input) do + send(name).send(input) + end + + define_method("#{input}=") do |value| + send(name).send("#{input}=", value) + end + end + end + # Import filters from another interaction. # # @param klass [Class] The other interaction. @@ -156,6 +173,7 @@ def initialize_filter(filter) def initialize(inputs = {}) fail ArgumentError, 'inputs must be a hash' unless inputs.is_a?(Hash) + process_proxies(self.class.instance_variable_get(:@_proxies) || Set.new) process_inputs(inputs.symbolize_keys) end @@ -254,5 +272,12 @@ def type_check end end end + + def process_proxies(proxies) + proxies.each do |name| + klass = name.to_s.camelize.constantize.new + instance_variable_set("@#{name}", klass) + end + end end end diff --git a/lib/active_interaction/concerns/runnable.rb b/lib/active_interaction/concerns/runnable.rb index 744f5af1..76fabfea 100644 --- a/lib/active_interaction/concerns/runnable.rb +++ b/lib/active_interaction/concerns/runnable.rb @@ -52,24 +52,6 @@ def valid?(*) super end - private - - # @param other [Class] The other interaction. - # @param (see ClassMethods.run) - # - # @return (see #result) - # - # @raise [Interrupt] - def compose(other, *args) - outcome = other.run(*args) - - if outcome.valid? - outcome.result - else - fail Interrupt, outcome - end - end - # @return (see #result=) # @return [nil] def run @@ -83,12 +65,6 @@ def run end end - def merge_errors_onto_base(new_errors) - new_errors.full_messages.each do |message| - errors.add(:base, message) unless errors.added?(:base, message) - end - end - # @return [Object] # # @raise [InvalidInteractionError] If there are validation errors. @@ -102,6 +78,30 @@ def run! end end + private + + # @param other [Class] The other interaction. + # @param (see ClassMethods.run) + # + # @return (see #result) + # + # @raise [Interrupt] + def compose(other, *args) + outcome = other.run(*args) + + if outcome.valid? + outcome.result + else + fail Interrupt, outcome + end + end + + def merge_errors_onto_base(new_errors) + new_errors.full_messages.each do |message| + errors.add(:base, message) unless errors.added?(:base, message) + end + end + # module ClassMethods def new(*) diff --git a/spec/active_interaction/base_spec.rb b/spec/active_interaction/base_spec.rb index 4294f842..2659267e 100644 --- a/spec/active_interaction/base_spec.rb +++ b/spec/active_interaction/base_spec.rb @@ -18,6 +18,16 @@ def execute end end +ProxyInteraction = Class.new(TestInteraction) do + float :x, :y + + proxy :add_interaction, %i[x y] + + def execute + add_interaction.run! + end +end + InterruptInteraction = Class.new(TestInteraction) do model :x, :y, class: Object, @@ -347,6 +357,17 @@ def execute end end + describe '#proxy' do + let(:described_class) { ProxyInteraction } + let(:x) { rand } + let(:y) { rand } + let(:inputs) { { x: x, y: y } } + + it 'works' do + expect(result).to eql x + y + end + end + describe '#compose' do let(:described_class) { InterruptInteraction } let(:x) { rand }