From f258b6ae05ebb8862c224a0de5d6e353d0e29e95 Mon Sep 17 00:00:00 2001 From: Mark Burns Date: Mon, 22 Jan 2024 07:06:48 +0000 Subject: [PATCH] extract modules to make code structure more apparent --- lib/interactify.rb | 94 ++----------------------- lib/interactify/configure.rb | 15 ++++ lib/interactify/contracts/breaches.rb | 26 +++++++ lib/interactify/contracts/helpers.rb | 18 ++--- lib/interactify/dependency_inference.rb | 56 +++++++++++++++ lib/interactify/hooks.rb | 25 +++++++ 6 files changed, 132 insertions(+), 102 deletions(-) create mode 100644 lib/interactify/configure.rb create mode 100644 lib/interactify/contracts/breaches.rb create mode 100644 lib/interactify/dependency_inference.rb create mode 100644 lib/interactify/hooks.rb diff --git a/lib/interactify.rb b/lib/interactify.rb index e02d27b..b3d2857 100644 --- a/lib/interactify.rb +++ b/lib/interactify.rb @@ -11,100 +11,16 @@ require "interactify/wiring" require "interactify/configuration" require "interactify/interactify_callable" - -module Interactify - class << self - delegate :on_definition_error, :trigger_definition_error, to: :configuration - - def railties_missing? - @railties_missing - end - - def railties_missing! - @railties_missing = true - end - - def railties - railties? - end - - def railties? - !railties_missing? - end - - def sidekiq_missing? - @sidekiq_missing - end - - def sidekiq_missing! - @sidekiq_missing = true - end - - def sidekiq - sidekiq? - end - - def sidekiq? - !sidekiq_missing? - end - end -end - -Interactify.instance_eval do - @sidekiq_missing = nil - @railties_missing = nil -end - -begin - require "sidekiq" -rescue LoadError - Interactify.sidekiq_missing! -end - -begin - require "rails/railtie" -rescue LoadError - Interactify.railties_missing! -end +require "interactify/dependency_inference" +require "interactify/hooks" +require "interactify/configure" module Interactify extend ActiveSupport::Concern + extend Hooks + extend Configure class << self - def validate_app(ignore: []) - Interactify::Wiring.new(root: Interactify.configuration.root, ignore:).validate_app - end - - def reset - @on_contract_breach = nil - @before_raise_hook = nil - @configuration = nil - end - - def trigger_contract_breach_hook(...) - @on_contract_breach&.call(...) - end - - def on_contract_breach(&block) - @on_contract_breach = block - end - - def trigger_before_raise_hook(...) - @before_raise_hook&.call(...) - end - - def before_raise(&block) - @before_raise_hook = block - end - - def configure - yield configuration - end - - def configuration - @configuration ||= Configuration.new - end - delegate :root, to: :configuration end diff --git a/lib/interactify/configure.rb b/lib/interactify/configure.rb new file mode 100644 index 0000000..1196416 --- /dev/null +++ b/lib/interactify/configure.rb @@ -0,0 +1,15 @@ +module Interactify + module Configure + def validate_app(ignore: []) + Interactify::Wiring.new(root: Interactify.configuration.root, ignore:).validate_app + end + + def configure + yield configuration + end + + def configuration + @configuration ||= Configuration.new + end + end +end diff --git a/lib/interactify/contracts/breaches.rb b/lib/interactify/contracts/breaches.rb new file mode 100644 index 0000000..bf395e2 --- /dev/null +++ b/lib/interactify/contracts/breaches.rb @@ -0,0 +1,26 @@ +module Interactify + module Breaches + def self.handle_with_failure(context, breaches) + breaches = preamble(context, breaches) + context.fail! contract_failures: breaches + end + + def self.handle_with_exception(context, failure_klass, breaches) + breaches = preamble(context, breaches) + + # e.g. raises + # SomeNamespace::SomeClass::ContractFailure, {whatever: 'is missing'} + # but also sending the context into Sentry + exception = failure_klass.new(breaches.to_json) + Interactify.trigger_before_raise_hook(exception) + raise exception + end + + def self.preamble(context, breaches) + breaches = breaches.map { |b| { b.property => b.messages } }.inject(&:merge) + + Interactify.trigger_contract_breach_hook(context, breaches) + breaches + end + end +end diff --git a/lib/interactify/contracts/helpers.rb b/lib/interactify/contracts/helpers.rb index c3e2329..16dc334 100644 --- a/lib/interactify/contracts/helpers.rb +++ b/lib/interactify/contracts/helpers.rb @@ -6,6 +6,7 @@ require "interactify/contracts/setup" require "interactify/contracts/promising" require "interactify/contracts/organizing" +require "interactify/contracts/breaches" require "interactify/dsl/organizer" module Interactify @@ -60,27 +61,18 @@ def _interactify_extract_keys(clauses) # rubocop: enable Metrics/BlockLength included do - c = Class.new(Contracts::Failure) + failure_klass = Class.new(Contracts::Failure) # example self is Whatever::SomeInteractor # failure class: Whatever::SomeInteractor::InteractorContractFailure - const_set "InteractorContractFailure", c + const_set "InteractorContractFailure", failure_klass prepend Contracts::CallWrapper include Dsl::Organizer on_breach do |breaches| - breaches = breaches.map { |b| { b.property => b.messages } }.inject(&:merge) - - Interactify.trigger_contract_breach_hook(context, breaches) - if @_interactor_called_by_non_bang_method == true - context.fail! contract_failures: breaches + Breaches.handle_with_failure(context, breaches) else - # e.g. raises - # SomeNamespace::SomeClass::ContractFailure, {whatever: 'is missing'} - # but also sending the context into Sentry - exception = c.new(breaches.to_json) - Interactify.trigger_before_raise_hook(exception) - raise exception + Breaches.handle_with_exception(context, failure_klass, breaches) end end end diff --git a/lib/interactify/dependency_inference.rb b/lib/interactify/dependency_inference.rb new file mode 100644 index 0000000..e74d2a4 --- /dev/null +++ b/lib/interactify/dependency_inference.rb @@ -0,0 +1,56 @@ +module Interactify + class << self + delegate :on_definition_error, :trigger_definition_error, to: :configuration + + def railties_missing? + @railties_missing + end + + def railties_missing! + @railties_missing = true + end + + def railties + railties? + end + + def railties? + !railties_missing? + end + + def sidekiq_missing? + @sidekiq_missing + end + + def sidekiq_missing! + @sidekiq_missing = true + end + + def sidekiq + sidekiq? + end + + def sidekiq? + !sidekiq_missing? + end + end +end + +Interactify.instance_eval do + @sidekiq_missing = nil + @railties_missing = nil +end + +begin + require "sidekiq" +rescue LoadError + Interactify.sidekiq_missing! +end + +begin + require "rails/railtie" +rescue LoadError + Interactify.railties_missing! +end + + diff --git a/lib/interactify/hooks.rb b/lib/interactify/hooks.rb new file mode 100644 index 0000000..5b52883 --- /dev/null +++ b/lib/interactify/hooks.rb @@ -0,0 +1,25 @@ +module Interactify + module Hooks + def reset + @on_contract_breach = nil + @before_raise_hook = nil + @configuration = nil + end + + def trigger_contract_breach_hook(...) + @on_contract_breach&.call(...) + end + + def on_contract_breach(&block) + @on_contract_breach = block + end + + def trigger_before_raise_hook(...) + @before_raise_hook&.call(...) + end + + def before_raise(&block) + @before_raise_hook = block + end + end +end