Class: Interaktor::Interaction
- Inherits:
-
Object
- Object
- Interaktor::Interaction
- Defined in:
- lib/interaktor/interaction.rb
Instance Attribute Summary collapse
- #failure_object ⇒ FailureAttributesModel? readonly
- #input_object ⇒ InputAttributesModel? readonly
- #success_object ⇒ SuccessAttributesModel? readonly
Instance Method Summary collapse
-
#_called ⇒ Array<Interaktor>
An array of successfully called Interaktor instances invoked against this interaction instance.
-
#called!(interaktor) ⇒ Object
Track that an Interaktor has been called.
-
#early_return! ⇒ Object
Trigger an early return throw.
-
#early_return? ⇒ Boolean
Whether or not the interaction has been returned from early.
- #fail!(args = {}) ⇒ Object
-
#failure? ⇒ Boolean
Whether the interaction has failed.
-
#initialize(interaktor, input) ⇒ Interaction
constructor
A new instance of Interaction.
-
#method_missing(method_name, *args, &block) ⇒ Object
Only allow access to arguments when appropriate.
- #respond_to_missing?(method_name, include_private = false) ⇒ Boolean
-
#rollback! ⇒ Boolean
Roll back the interaction.
- #success!(args = {}) ⇒ Object
-
#success? ⇒ Boolean
Whether the interaction is successful.
Constructor Details
#initialize(interaktor, input) ⇒ Interaction
Returns a new instance of Interaction.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/interaktor/interaction.rb', line 16 def initialize(interaktor, input) @interaktor = interaktor @executed = false @failed = false @rolled_back = false @input_object = if defined?(interaktor.class::InputAttributesModel) result = interaktor.class::InputAttributesModel.new case input when Hash input.each do |k, v| result.send("#{k}=", v) rescue NoMethodError => e if e.receiver == result raise Interaktor::Error::UnknownAttributeError.new(interaktor, k) else raise e end end when Interaction (input.input_object&.attributes || {}) .merge(input.success_object&.attributes || {}) .slice(*result.attribute_names) .each { |k, v| result.send("#{k}=", v) } else raise ArgumentError, "Invalid input type: #{input.class}" end if !result.valid? raise Interaktor::Error::AttributeValidationError.new(@interaktor, result) end result elsif input.is_a?(Hash) && !input.empty? raise Interaktor::Error::UnknownAttributeError.new(interaktor, input.keys.first) end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
Only allow access to arguments when appropriate. Input arguments should be accessible only during the interaction's execution, and after the execution is complete, either the success or failure arguments should be accessible, depending on the outcome.
146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/interaktor/interaction.rb', line 146 def method_missing(method_name, *args, &block) method_string = method_name.to_s if !@executed && input_object&.attribute_names&.include?(method_string) input_object.send(method_string) elsif @executed && success? && success_object&.attribute_names&.include?(method_string) success_object.send(method_string) elsif @executed && failure? && failure_object&.attribute_names&.include?(method_string) failure_object.send(method_string) else super end end |
Instance Attribute Details
#failure_object ⇒ FailureAttributesModel? (readonly)
12 13 14 |
# File 'lib/interaktor/interaction.rb', line 12 def failure_object @failure_object end |
#input_object ⇒ InputAttributesModel? (readonly)
6 7 8 |
# File 'lib/interaktor/interaction.rb', line 6 def input_object @input_object end |
#success_object ⇒ SuccessAttributesModel? (readonly)
9 10 11 |
# File 'lib/interaktor/interaction.rb', line 9 def success_object @success_object end |
Instance Method Details
#_called ⇒ Array<Interaktor>
An array of successfully called Interaktor instances invoked against this interaction instance.
193 194 195 |
# File 'lib/interaktor/interaction.rb', line 193 def _called @called ||= [] end |
#called!(interaktor) ⇒ Object
Track that an Interaktor has been called. The #called! method is used by
the interaktor being invoked. After an interaktor is successfully called,
the interaction is tracked for the purpose of potential future rollback.
184 185 186 187 |
# File 'lib/interaktor/interaction.rb', line 184 def called!(interaktor) @executed = true _called << interaktor end |
#early_return! ⇒ Object
Trigger an early return throw.
198 199 200 201 |
# File 'lib/interaktor/interaction.rb', line 198 def early_return! @early_return = true throw :early_return, self end |
#early_return? ⇒ Boolean
Whether or not the interaction has been returned from early.
204 205 206 |
# File 'lib/interaktor/interaction.rb', line 204 def early_return? (@early_return == true) || false end |
#fail!(args = {}) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/interaktor/interaction.rb', line 82 def fail!(args = {}) if @executed raise Interaktor::Error::InvalidMethodForStateError.new( self, "Cannot call `fail!` after interaktor execution is already complete" ) end @executed = true @failed = true if defined?(@interaktor.class::FailureAttributesModel) @failure_object = @interaktor.class::FailureAttributesModel.new.tap do |obj| args.each do |k, v| obj.send("#{k}=", v) rescue NoMethodError raise Interaktor::Error::UnknownAttributeError.new(@interaktor, k) end if !obj.valid? raise Interaktor::Error::AttributeValidationError.new(@interaktor, obj) end end elsif args.any? raise Interaktor::Error::UnknownAttributeError.new(@interaktor, args.keys.first) end raise Interaktor::Failure, self end |
#failure? ⇒ Boolean
Whether the interaction has failed.
68 69 70 71 72 73 74 75 76 77 |
# File 'lib/interaktor/interaction.rb', line 68 def failure? if !@executed raise Interaktor::Error::InvalidMethodForStateError.new( self, "Cannot call `failure?` before interaktor execution is complete" ) end @failed end |
#respond_to_missing?(method_name, include_private = false) ⇒ Boolean
159 160 161 162 163 164 |
# File 'lib/interaktor/interaction.rb', line 159 def respond_to_missing?(method_name, include_private = false) input_object&.attribute_names&.include?(method_name) || success_object&.attribute_names&.include?(method_name) || failure_object&.attribute_names&.include?(method_name) || super end |
#rollback! ⇒ Boolean
Roll back the interaction. Successful interactions may have this method called to roll back their state.
171 172 173 174 175 176 |
# File 'lib/interaktor/interaction.rb', line 171 def rollback! return false if @rolled_back _called.reverse_each(&:rollback) @rolled_back = true end |
#success!(args = {}) ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/interaktor/interaction.rb', line 113 def success!(args = {}) if @executed raise Interaktor::Error::InvalidMethodForStateError.new( self, "Cannot call `success!` after interaktor execution is already complete" ) end @executed = true if defined?(@interaktor.class::SuccessAttributesModel) @success_object = @interaktor.class::SuccessAttributesModel.new.tap do |obj| args.each do |k, v| obj.send("#{k}=", v) rescue NoMethodError raise Interaktor::Error::UnknownAttributeError.new(@interaktor, k) end if !obj.valid? raise Interaktor::Error::AttributeValidationError.new(@interaktor, obj) end end elsif args.any? raise Interaktor::Error::UnknownAttributeError.new(@interaktor, args.keys.first) end early_return! end |
#success? ⇒ Boolean
Whether the interaction is successful.
56 57 58 59 60 61 62 63 64 65 |
# File 'lib/interaktor/interaction.rb', line 56 def success? if !@executed raise Interaktor::Error::InvalidMethodForStateError.new( self, "Cannot call `success?` before interaktor execution is complete" ) end !failure? end |