module Ni::Main::ClassMethods
Attributes
defined_actions[RW]
Public Instance Methods
action(*args, &block)
click to toggle source
# File lib/ni/main.rb, line 134 def action(*args, &block) self.defined_actions ||= {} name, description = args description ||= 'No description' ActionChain.new(self, name, description, &block) ensure unless respond_to?(name) define_singleton_method name do |*args, **params| context = args.first perform_custom(name, context, params) end end end
action_by_name(name)
click to toggle source
# File lib/ni/main.rb, line 306 def action_by_name(name) return nil unless defined_actions.present? action = defined_actions.find { |(action_name, _), _| action_name == name } Array(action).last end
define_action!(name)
click to toggle source
# File lib/ni/main.rb, line 182 def define_action!(name) raise 'Action not described' unless action_by_name(name).present? action_units = action_by_name(name).units action_failure_callback = action_by_name(name).failure_callback action_exceptions = action_by_name(name).rescues define_method name do if context.should_be_restored? unless self.class.context_storage_klass.present? && self.class.metadata_repository_klass.present? raise "Storages was not configured" end self.class.context_storage_klass.new(context, self.class.metadata_repository_klass).fetch on_context_restored(name) end before_action(name) action_units.each do |unit| return if context.execution_halted? return if context.chain_skipped? if context.wait_for_execution? # Send to other interactor chain if unit.respond_to?(:handle_current_wait?) && unit.handle_current_wait?(context, context.continue_from) rescue_callback, ex = safe_context name do handle_exceptions action_exceptions do unit.call_for_wait_continue(self.context, wait_completed_for: context.continue_from, system_uid: context.system_uid) end end next unless rescue_callback.present? elsif unit.is_a?(Ni::Flows::WaitForCondition) on_checking_continue_signal(unit) wait_cheking_result = unit.wait_or_continue(context.continue_from, context, self.class.metadata_repository_klass) on_continue_signal_checked(unit, wait_cheking_result) case wait_cheking_result when Ni::Flows::WaitForCondition::SKIP next when Ni::Flows::WaitForCondition::WAIT return when Ni::Flows::WaitForCondition::COMPLETED context.wait_completed! unit.clear_timer!(context, self.class.metadata_repository_klass) next end else next end end # This can't be replaced with if ... else # The wait checking hooks can change the context so need to ensure if block can be performed # And from other side the performing block is also able to change context and terminate execution if can_perform_next_step? # Previous step could send flow to existing chain rescue_callback, ex = safe_context name do handle_exceptions action_exceptions do if unit.is_a?(Proc) instance_eval(&unit) elsif unit.is_a?(Symbol) send(unit) elsif unit.is_a?(String) unit.to_s.split('.').reduce(self) {|memo, name| memo.send(name) } elsif unit.kind_of?(Ni::Flows::Base) unit.call(self.context) elsif unit.kind_of?(Ni::Flows::WaitForCondition) if self.class.context_storage_klass.present? && self.class.metadata_repository_klass.present? self.class.context_storage_klass.new(context, self.class.metadata_repository_klass).store else raise "WaitFor require a store and metadata repository" end unit.setup_timer!(context, self.class.metadata_repository_klass) context.halt_execution! return end end end if rescue_callback.present? instance_exec(ex, &rescue_callback) context.failure! end end unless can_perform_next_step? instance_eval(&action_failure_callback) if context.failed? && action_failure_callback.present? { :failed? => :on_failure, :canceled? => :on_cancel, :terminated? => :on_terminate }.each do |predicate, callback| if context.public_send(predicate) if unit.respond_to?(callback) && unit.public_send(callback).present? if unit.public_send(callback).is_a?(Proc) instance_exec(&unit.public_send(callback)) end if unit.public_send(callback).is_a?(Class) unit.public_send(callback).perform(context) end end self.public_send(callback, name) end end after_action(name) return end end after_action(name) on_success(name) end end
define_actions!()
click to toggle source
# File lib/ni/main.rb, line 178 def define_actions! defined_actions.keys.map(&:first).each { |name| define_action!(name) } end
interactor_id()
click to toggle source
without specified ID will use class name
# File lib/ni/main.rb, line 126 def interactor_id @unique_interactor_id || name end
interactor_id!()
click to toggle source
# File lib/ni/main.rb, line 130 def interactor_id! @unique_interactor_id || raise("The #{self.name} requires an explicit definition of the unique id") end
perform(*args, **params)
click to toggle source
# File lib/ni/main.rb, line 153 def perform(*args, **params) context = args.first perform_custom(:perform, context, params) end
perform_custom(*args, **params)
click to toggle source
# File lib/ni/main.rb, line 159 def perform_custom(*args, **params) object = self.new name, context = args system_uid = params.delete(:system_uid) wait_completed_for = params.delete(:wait_completed_for) context ||= Ni::Context.new(object, name, system_uid) context.continue_from!(wait_completed_for) if wait_completed_for.present? context.assign_data!(params) context.assign_current_interactor!(object) object.context = context object.public_send(name) Ni::Result.new object.context.resultify!, object.returned_values(name) end
unique_id(id=nil)
click to toggle source
# File lib/ni/main.rb, line 120 def unique_id(id=nil) @unique_interactor_id = id Ni::Main.register_unique_interactor(interactor_id, self) end
units_by_interface(interface)
click to toggle source
# File lib/ni/main.rb, line 314 def units_by_interface(interface) defined_actions.values.map(&:units).flatten.select { |u| u.respond_to?(interface) } end