forked from collectiveidea/interactor
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from hedgesky/allow_conditional_execution_of_or…
…ganized_interactors Support conditional execution of organized interactors (Fixes collectiveidea#128)
- Loading branch information
Showing
6 changed files
with
201 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
module Interactor | ||
# Internal: this class allows us to run interactors with regard of given | ||
# options, such as :if, :unless, :before, :after | ||
class OrganizedInteractor | ||
attr_reader :interactor, :options | ||
|
||
def initialize(interactor, options = {}) | ||
@interactor = interactor | ||
@options = options | ||
end | ||
|
||
def call!(context, within_organizer) | ||
interactor.call!(context) if permitted_to_call?(within_organizer) | ||
end | ||
|
||
private | ||
|
||
def permitted_to_call?(organizer) | ||
permitted_by_if?(organizer) && permitted_by_unless?(organizer) | ||
end | ||
|
||
def permitted_by_if?(organizer) | ||
return true unless options[:if] | ||
execute_within_organizer(organizer, options[:if]) | ||
end | ||
|
||
def permitted_by_unless?(organizer) | ||
return true unless options[:unless] | ||
!execute_within_organizer(organizer, options[:unless]) | ||
end | ||
|
||
def execute_within_organizer(organizer, symbol_or_proc) | ||
if symbol_or_proc.is_a?(Symbol) | ||
symbol_or_proc.to_proc.call(organizer) | ||
else | ||
organizer.instance_exec(&symbol_or_proc) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
require "ostruct" | ||
|
||
module Interactor | ||
describe OrganizedInteractor do | ||
let(:interactor) { double(:interactor, call!: nil) } | ||
let(:organizer) { FakeOrganizer.new } | ||
let(:context) { double(:context) } | ||
|
||
class FakeOrganizer | ||
def context | ||
OpenStruct.new(truthy: true, falsey: false) | ||
end | ||
|
||
def truthy_method | ||
true | ||
end | ||
|
||
def falsey_method | ||
false | ||
end | ||
end | ||
|
||
def build_with_options_and_call(options) | ||
OrganizedInteractor.new(interactor, options).call!(context, organizer) | ||
end | ||
|
||
describe "#call!" do | ||
it "runs an interactor" do | ||
OrganizedInteractor.new(interactor).call!(context, organizer) | ||
expect(interactor).to have_received(:call!).with(context) | ||
end | ||
|
||
context "when :if option is a proc" do | ||
it "evaluates it within an organizer" do | ||
expect(organizer).to receive(:truthy_method).and_call_original | ||
build_with_options_and_call(if: -> { truthy_method }) | ||
end | ||
|
||
it "runs an interactor if proc evaluation was truthy" do | ||
build_with_options_and_call(if: -> { context.truthy }) | ||
expect(interactor).to have_received(:call!) | ||
end | ||
|
||
it "doesn't run an interactor if proc evaluation was falsey" do | ||
build_with_options_and_call(if: -> { context.falsey }) | ||
expect(interactor).not_to have_received(:call!) | ||
end | ||
end | ||
|
||
context "when :unless option is a proc" do | ||
it "evaluates it within an organizer" do | ||
expect(organizer).to receive(:truthy_method).and_call_original | ||
build_with_options_and_call(unless: -> { truthy_method }) | ||
end | ||
|
||
it "runs an interactor if proc evaluation was falsey" do | ||
build_with_options_and_call(unless: -> { context.falsey }) | ||
expect(interactor).to have_received(:call!) | ||
end | ||
|
||
it "doesn't run an interactor if proc evaluation was truthy" do | ||
build_with_options_and_call(unless: -> { context.truthy }) | ||
expect(interactor).not_to have_received(:call!) | ||
end | ||
end | ||
|
||
context "when :if option is a symbol" do | ||
it "treats it as organizer's method name" do | ||
expect(organizer).to receive(:truthy_method).and_call_original | ||
build_with_options_and_call(if: :truthy_method) | ||
end | ||
|
||
it "runs an interactor if method evaluation was truthy" do | ||
build_with_options_and_call(if: :truthy_method) | ||
expect(interactor).to have_received(:call!) | ||
end | ||
|
||
it "doesn't run an interactor if method evaluation was falsey" do | ||
build_with_options_and_call(if: :falsey_method) | ||
expect(interactor).not_to have_received(:call!) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters