From 55ac5e08c41e16ae097db70bf8f426f57f733535 Mon Sep 17 00:00:00 2001 From: Mark Burns Date: Sat, 30 Dec 2023 10:42:15 +0000 Subject: [PATCH] ensure we correctly wrap nested classes --- lib/interactify/dsl/each_chain.rb | 12 ++- spec/fixtures/asdf | 0 .../app/interactors/all_the_things.rb | 59 +++++++++++++++ .../integration_app/app/interactors/each/a.rb | 13 ++++ .../integration_app/app/interactors/each/b.rb | 13 ++++ .../integration_app/app/interactors/each/c.rb | 13 ++++ .../integration_app/app/interactors/each/d.rb | 13 ++++ .../app/interactors/each/organizer.rb | 10 +++ .../integration_app/app/interactors/if/a.rb | 13 ++++ .../integration_app/app/interactors/if/b.rb | 13 ++++ .../integration_app/app/interactors/if/c.rb | 13 ++++ .../integration_app/app/interactors/if/d.rb | 13 ++++ .../app/interactors/if/organizer.rb | 40 ++++++++++ .../app/services/not_an_interactor.rb | 1 + .../all_the_things_integration_spec.rb | 63 ++++++++++++++++ spec/integration/each_integration_spec.rb | 27 +++++++ spec/integration/if_integration_spec.rb | 75 +++++++++++++++++++ 17 files changed, 388 insertions(+), 3 deletions(-) create mode 100644 spec/fixtures/asdf create mode 100644 spec/fixtures/integration_app/app/interactors/all_the_things.rb create mode 100644 spec/fixtures/integration_app/app/interactors/each/a.rb create mode 100644 spec/fixtures/integration_app/app/interactors/each/b.rb create mode 100644 spec/fixtures/integration_app/app/interactors/each/c.rb create mode 100644 spec/fixtures/integration_app/app/interactors/each/d.rb create mode 100644 spec/fixtures/integration_app/app/interactors/each/organizer.rb create mode 100644 spec/fixtures/integration_app/app/interactors/if/a.rb create mode 100644 spec/fixtures/integration_app/app/interactors/if/b.rb create mode 100644 spec/fixtures/integration_app/app/interactors/if/c.rb create mode 100644 spec/fixtures/integration_app/app/interactors/if/d.rb create mode 100644 spec/fixtures/integration_app/app/interactors/if/organizer.rb create mode 100644 spec/fixtures/integration_app/app/services/not_an_interactor.rb create mode 100644 spec/integration/all_the_things_integration_spec.rb create mode 100644 spec/integration/each_integration_spec.rb create mode 100644 spec/integration/if_integration_spec.rb diff --git a/lib/interactify/dsl/each_chain.rb b/lib/interactify/dsl/each_chain.rb index b937a21..3f77ba8 100644 --- a/lib/interactify/dsl/each_chain.rb +++ b/lib/interactify/dsl/each_chain.rb @@ -41,9 +41,7 @@ def klass context[this.singular_resource_name] = resource # context.package = package context[this.singular_resource_index_name] = index # context.package_index = index - klasses = Wrapper.wrap_many(self, this.each_loop_klasses) - - klasses.each do |interactor| # [A, B, C].each do |interactor| + self.class.klasses.each do |interactor| # [A, B, C].each do |interactor| interactor.call!(context) # interactor.call!(context) end # end end # end @@ -54,6 +52,14 @@ def klass context # context end # end + define_singleton_method(:klasses) do # def self.klasses + klasses = instance_variable_get(:@klasses) # @klasses ||= Wrapper.wrap_many(self, [A, B, C]) + return klasses if klasses + + instance_variable_set(:@klasses, Wrapper.wrap_many(self, this.each_loop_klasses)) + end + + # "" define_method(:inspect) do "<#{this.namespace}::#{this.iterator_klass_name} iterates_over: #{this.each_loop_klasses.inspect}>" end diff --git a/spec/fixtures/asdf b/spec/fixtures/asdf new file mode 100644 index 0000000..e69de29 diff --git a/spec/fixtures/integration_app/app/interactors/all_the_things.rb b/spec/fixtures/integration_app/app/interactors/all_the_things.rb new file mode 100644 index 0000000..60732b4 --- /dev/null +++ b/spec/fixtures/integration_app/app/interactors/all_the_things.rb @@ -0,0 +1,59 @@ +class AllTheThings + include Interactify + + expect :things + optional :optional_thing + promise :a + + organize \ + self.if( + :things, + then: [If::A, If::B], + else: [If::C, If::D] + ), + + self.each( + :things, + If::A, + If::B, + -> (c) { c.lambda_set = true } + ), + + self.if( + -> (c) { c.a && c.b } , + then: -> (c) { c.both_a_and_b = true }, + else: -> (c) { c.both_a_and_b = false} + ), + + -> (c) { c.more_things = [1, 2, 3, 4] }, + + self.each( + :more_things, + -> (c) { + if c.more_thing_index.zero? + c.first_more_thing = true + end + }, + -> (c) { + if c.more_thing_index == 1 + c.next_more_thing = true + end + }, + {if: :not_set_thing, then: -> (c) { c.not_set_thing = true } }, + -> (c) { c.more_thing = true } + ), + + self.if( + :optional_thing, + then: [ + -> (c) { c.optional_thing_was_set = true }, + -> (c) { c.and_then_another_thing = true }, + -> (c) { c.and_one_more_thing = true }, + self.each(:more_things, + -> (c) { c.more_things[c.more_thing_index] = c.more_thing + 5 }, + -> (c) { c.more_things[c.more_thing_index] = c.more_thing + 5 } + ) + ], + else: -> (c) { c.optional_thing_was_set = false } + ) +end diff --git a/spec/fixtures/integration_app/app/interactors/each/a.rb b/spec/fixtures/integration_app/app/interactors/each/a.rb new file mode 100644 index 0000000..58e4d70 --- /dev/null +++ b/spec/fixtures/integration_app/app/interactors/each/a.rb @@ -0,0 +1,13 @@ +module Each + class A + include Interactify + + def call + context.a = 'a' + return unless context.thing + + context.thing.a = 'a' + context.thing.a_index = context.thing_index + end + end +end diff --git a/spec/fixtures/integration_app/app/interactors/each/b.rb b/spec/fixtures/integration_app/app/interactors/each/b.rb new file mode 100644 index 0000000..59fb7ec --- /dev/null +++ b/spec/fixtures/integration_app/app/interactors/each/b.rb @@ -0,0 +1,13 @@ +module Each + class B + include Interactify + + def call + context.b = 'b' + return unless context.thing + + context.thing.b = 'b' + context.thing.b_index = context.thing_index + end + end +end diff --git a/spec/fixtures/integration_app/app/interactors/each/c.rb b/spec/fixtures/integration_app/app/interactors/each/c.rb new file mode 100644 index 0000000..1f332cf --- /dev/null +++ b/spec/fixtures/integration_app/app/interactors/each/c.rb @@ -0,0 +1,13 @@ +module Each + class C + include Interactify + + def call + context.c = 'c' + return unless context.thing + + context.thing.c = 'c' + context.thing.c_index = context.thing_index + end + end +end diff --git a/spec/fixtures/integration_app/app/interactors/each/d.rb b/spec/fixtures/integration_app/app/interactors/each/d.rb new file mode 100644 index 0000000..9f9099c --- /dev/null +++ b/spec/fixtures/integration_app/app/interactors/each/d.rb @@ -0,0 +1,13 @@ +module Each + class D + include Interactify + + def call + context.d = 'd' + return unless context.thing + + context.thing.d = 'd' + context.thing.d_index = context.thing_index + end + end +end diff --git a/spec/fixtures/integration_app/app/interactors/each/organizer.rb b/spec/fixtures/integration_app/app/interactors/each/organizer.rb new file mode 100644 index 0000000..cfed970 --- /dev/null +++ b/spec/fixtures/integration_app/app/interactors/each/organizer.rb @@ -0,0 +1,10 @@ +module Each + class Organizer + include Interactify + expect :things + + organize \ + A, B, C, D, + self.each(:things, A, B, C, D) + end +end diff --git a/spec/fixtures/integration_app/app/interactors/if/a.rb b/spec/fixtures/integration_app/app/interactors/if/a.rb new file mode 100644 index 0000000..08921f3 --- /dev/null +++ b/spec/fixtures/integration_app/app/interactors/if/a.rb @@ -0,0 +1,13 @@ +module If + class A + include Interactify + + def call + context.a = 'a' + return unless context.thing + + context.thing.a = 'a' + context.thing.a_index = context.thing_index + end + end +end diff --git a/spec/fixtures/integration_app/app/interactors/if/b.rb b/spec/fixtures/integration_app/app/interactors/if/b.rb new file mode 100644 index 0000000..26fd20b --- /dev/null +++ b/spec/fixtures/integration_app/app/interactors/if/b.rb @@ -0,0 +1,13 @@ +module If + class B + include Interactify + + def call + context.b = 'b' + return unless context.thing + + context.thing.b = 'b' + context.thing.b_index = context.thing_index + end + end +end diff --git a/spec/fixtures/integration_app/app/interactors/if/c.rb b/spec/fixtures/integration_app/app/interactors/if/c.rb new file mode 100644 index 0000000..54039fb --- /dev/null +++ b/spec/fixtures/integration_app/app/interactors/if/c.rb @@ -0,0 +1,13 @@ +module If + class C + include Interactify + + def call + context.c = 'c' + return unless context.thing + + context.thing.c = 'c' + context.thing.c_index = context.thing_index + end + end +end diff --git a/spec/fixtures/integration_app/app/interactors/if/d.rb b/spec/fixtures/integration_app/app/interactors/if/d.rb new file mode 100644 index 0000000..5d0942f --- /dev/null +++ b/spec/fixtures/integration_app/app/interactors/if/d.rb @@ -0,0 +1,13 @@ +module If + class D + include Interactify + + def call + context.d = 'd' + return unless context.thing + + context.thing.d = 'd' + context.thing.d_index = context.thing_index + end + end +end diff --git a/spec/fixtures/integration_app/app/interactors/if/organizer.rb b/spec/fixtures/integration_app/app/interactors/if/organizer.rb new file mode 100644 index 0000000..4fc4551 --- /dev/null +++ b/spec/fixtures/integration_app/app/interactors/if/organizer.rb @@ -0,0 +1,40 @@ +module If + class Anyways + include Interactify + + expect :blah, filled: false + + def call + context.anyways = blah + end + end + + class MethodSyntaxOrganizer + include Interactify + expect :blah, filled: false + + organize \ + self.if(:blah, [A, B], [C, D]), + Anyways + end + + class AlternativeMethodSyntaxOrganizer + include Interactify + expect :blah, filled: false + + organize( + self.if(:blah, then: [A, B], else: [C, D]), + Anyways + ) + end + + class HashSyntaxOrganizer + include Interactify + expect :blah, filled: false + + organize( + {if: :blah, then: [A, B], else: [C, D]}, + Anyways + ) + end +end diff --git a/spec/fixtures/integration_app/app/services/not_an_interactor.rb b/spec/fixtures/integration_app/app/services/not_an_interactor.rb new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/spec/fixtures/integration_app/app/services/not_an_interactor.rb @@ -0,0 +1 @@ + diff --git a/spec/integration/all_the_things_integration_spec.rb b/spec/integration/all_the_things_integration_spec.rb new file mode 100644 index 0000000..a984cb8 --- /dev/null +++ b/spec/integration/all_the_things_integration_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +RSpec.describe "Interactify" do + let(:things) do + [thing1, thing2] + end + + let(:thing1) do + OpenStruct.new + end + + let(:thing2) do + OpenStruct.new + end + + before do + require_files("each/") + require_files("if/") + require_files('') + end + + context 'without an optional thing' do + let(:result) { AllTheThings.promising(:a).call!(things:, optional_thing: false) } + + it "sets A and B, then lambda_set, then both_a_and_b, then first_more_thing, next_more_thing" do + expect(result.a).to eq("a") + expect(result.b).to eq("b") + expect(result.c).to eq(nil) + expect(result.d).to eq(nil) + expect(result.lambda_set).to eq(true) + expect(result.both_a_and_b).to eq(true) + expect(result.more_things).to eq([1, 2, 3, 4]) + expect(result.first_more_thing).to eq(true) + expect(result.next_more_thing).to eq(true) + expect(result.optional_thing_was_set).to eq(false) + end + end + + context "with an optional thing" do + let(:result) { AllTheThings.promising(:a).call!(things:, optional_thing: true) } + + it "sets A and B, then lambda_set, then both_a_and_b, then first_more_thing, next_more_thing" do + expect(result.a).to eq("a") + expect(result.b).to eq("b") + expect(result.c).to eq(nil) + expect(result.d).to eq(nil) + expect(result.lambda_set).to eq(true) + expect(result.both_a_and_b).to eq(true) + expect(result.more_things).to eq([6, 7, 8, 9]) + expect(result.first_more_thing).to eq(true) + expect(result.next_more_thing).to eq(true) + expect(result.optional_thing_was_set).to eq(true) + end + end + + def require_files(dir) + files = Dir.glob("./spec/fixtures/integration_app/app/interactors/#{dir}**/*.rb") + + files.each do |file| + require file + end + end +end diff --git a/spec/integration/each_integration_spec.rb b/spec/integration/each_integration_spec.rb new file mode 100644 index 0000000..1064bf5 --- /dev/null +++ b/spec/integration/each_integration_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +RSpec.describe "Interactify.each" do + before do + files = Dir.glob("./spec/fixtures/integration_app/app/interactors/each/**/*.rb") + files.each do |file| + require file + end + end + + let(:thing_1) do + OpenStruct.new + end + + let(:thing_2) do + OpenStruct.new + end + + it "runs the outer interactors" do + result = Each::Organizer.call!(things: [thing_1, thing_2]) + + expect(result.a).to eq("a") + expect(result.b).to eq("b") + expect(result.c).to eq("c") + expect(result.d).to eq("d") + end +end diff --git a/spec/integration/if_integration_spec.rb b/spec/integration/if_integration_spec.rb new file mode 100644 index 0000000..5ec29ab --- /dev/null +++ b/spec/integration/if_integration_spec.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +RSpec.describe "Interactify.if" do + before do + files = Dir.glob("./spec/fixtures/integration_app/app/interactors/if/**/*.rb") + files.each do |file| + require file + end + end + + let(:thing_1) do + OpenStruct.new + end + + let(:thing_2) do + OpenStruct.new + end + + context "with method syntax" do + let(:truthy_result) { If::MethodSyntaxOrganizer.call!(blah: true) } + let(:falsey_result) { If::MethodSyntaxOrganizer.call!(blah: false) } + + it "runs the relevant clauses" do + expect(truthy_result.a).to eq("a") + expect(truthy_result.b).to eq("b") + expect(truthy_result.c).to eq(nil) + expect(truthy_result.d).to eq(nil) + expect(truthy_result.anyways).to eq(true) + + expect(falsey_result.a).to eq(nil) + expect(falsey_result.b).to eq(nil) + expect(falsey_result.c).to eq("c") + expect(falsey_result.d).to eq("d") + expect(falsey_result.anyways).to eq(false) + end + end + + context "with alternative method syntax" do + let(:truthy_result) { If::AlternativeMethodSyntaxOrganizer.call!(blah: true) } + let(:falsey_result) { If::AlternativeMethodSyntaxOrganizer.call!(blah: false) } + + it "runs the relevant clauses" do + expect(truthy_result.a).to eq("a") + expect(truthy_result.b).to eq("b") + expect(truthy_result.c).to eq(nil) + expect(truthy_result.d).to eq(nil) + expect(truthy_result.anyways).to eq(true) + + expect(falsey_result.a).to eq(nil) + expect(falsey_result.b).to eq(nil) + expect(falsey_result.c).to eq("c") + expect(falsey_result.d).to eq("d") + expect(falsey_result.anyways).to eq(false) + end + end + + context "with hash syntax" do + let(:truthy_result) { If::HashSyntaxOrganizer.call!(blah: true) } + let(:falsey_result) { If::HashSyntaxOrganizer.call!(blah: false) } + + it "runs the relevant clauses" do + expect(truthy_result.a).to eq("a") + expect(truthy_result.b).to eq("b") + expect(truthy_result.c).to eq(nil) + expect(truthy_result.d).to eq(nil) + expect(truthy_result.anyways).to eq(true) + + expect(falsey_result.a).to eq(nil) + expect(falsey_result.b).to eq(nil) + expect(falsey_result.c).to eq("c") + expect(falsey_result.d).to eq("d") + expect(falsey_result.anyways).to eq(false) + end + end +end