Class: ActiveInteractor::Context::Base

Inherits:
OpenStruct
  • Object
show all
Includes:
ActiveModel::Validations
Defined in:
lib/active_interactor/context.rb

Overview

The base context class inherited by all Interactor::Context classes

Author:

Since:

  • 0.0.1

Version:

  • 0.1

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(interactor, attributes = {}) ⇒ ActiveInteractor::Context::Base

Parameters:

  • interactor (ActiveInteractor::Base)

    an interactor instance

  • attributes (Hash, nil) (defaults to: {})

    the attributes of the context

Since:

  • 0.0.1



47
48
49
50
51
# File 'lib/active_interactor/context.rb', line 47

def initialize(interactor, attributes = {})
  copy_flags!(attributes)
  @interactor = interactor
  super(attributes)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object

Attempt to call the interactor for missing validation callback methods

Raises:

  • (NameError)

    if the method is not a validation callback or method does not exist on the interactor instance

Since:

  • 0.0.1



218
219
220
221
# File 'lib/active_interactor/context.rb', line 218

def method_missing(name, *args, &block)
  interactor.send(name, *args, &block) if validation_callback?(name)
  super
end

Class Method Details

.attributesArray<Symbol>

Attributes defined on the context class

Examples:

Get attributes defined on a context class

MyInteractor::Context.attributes
#=> [:first_name, :last_name]

Returns:

  • (Array<Symbol>)

    the defined attributes

Since:

  • 0.0.1



61
62
63
64
65
66
# File 'lib/active_interactor/context.rb', line 61

def attributes
  __default_attributes
    .concat(_validate_callbacks.map(&:filter).map(&:attributes).flatten)
    .flatten
    .uniq
end

.attributes=(*attributes) ⇒ Array<Symbol>

Set attributes on a context class

Examples:

Define attributes on a context class

MyInteractor::Context.attributes = :first_name, :last_name
#=> [:first_name, :last_name]

Parameters:

  • attributes (Array<Symbol, String>)

Returns:

  • (Array<Symbol>)

    the defined attributes

Since:

  • 0.0.1



76
77
78
# File 'lib/active_interactor/context.rb', line 76

def attributes=(*attributes)
  self.__default_attributes = self.attributes.concat(attributes.flatten.map(&:to_sym)).uniq
end

Instance Method Details

#attributesHash{Symbol => *}

Attributes defined on the instance

Examples:

Get attributes defined on an instance

MyInteractor::Context.attributes = :first_name, :last_name
#=> [:first_name, :last_name]

context = MyInteractor::Context.new(first_name: 'Aaron', last_name: 'Allen')
#=> <#MyInteractor::Context first_name='Aaron', last_name='Allen'>

context.attributes
#=> { first_name: 'Aaron', last_name: 'Allen' }

Get attributes defined on an instance with unknown attribute

MyInteractor::Context.attributes = :first_name, :last_name
#=> [:first_name, :last_name]

context = MyInteractor::Context.new(first_name: 'Aaron', last_name: 'Allen', unknown: 'unknown')
#=> <#MyInteractor::Context first_name='Aaron', last_name='Allen', unknown='unknown'>

context.attributes
#=> { first_name: 'Aaron', last_name: 'Allen' }

context.unknown
#=> 'unknown'

Returns:

  • (Hash{Symbol => *})

    the defined attributes and values

Since:

  • 0.0.1



107
108
109
110
111
# File 'lib/active_interactor/context.rb', line 107

def attributes
  self.class.attributes.each_with_object({}) do |attribute, hash|
    hash[attribute] = self[attribute] if self[attribute]
  end
end

#called!Array<ActiveInteractor::Base>

Track that an Interactor has been called. The #called! method

is used by the interactor being invoked with this context. After an
interactor is successfully called, the interactor instance is tracked in
the context for the purpose of potential future rollback

Returns:

Since:

  • 0.0.1



119
120
121
# File 'lib/active_interactor/context.rb', line 119

def called!
  _called << interactor
end

#clean!Hash{Symbol => *}

Removes properties from the instance that are not explicitly defined in the context instance #attributes

Examples:

Clean an instance of Context with unknown attribute

MyInteractor::Context.attributes = :first_name, :last_name
#=> [:first_name, :last_name]

context = MyInteractor::Context.new(first_name: 'Aaron', last_name: 'Allen', unknown: 'unknown')
#=> <#MyInteractor::Context first_name='Aaron', last_name='Allen', unknown='unknown'>

context.unknown
#=> 'unknown'

context.clean!
#=> { unknown: 'unknown' }

context.unknown
#=> nil

Returns:

  • (Hash{Symbol => *})

    the deleted attributes

Since:

  • 0.0.1



143
144
145
146
147
148
149
150
151
152
# File 'lib/active_interactor/context.rb', line 143

def clean!
  deleted = {}
  return deleted if keys.empty?

  keys.reject { |key| self.class.attributes.include?(key) }.each do |attribute|
    deleted[attribute] = self[attribute] if self[attribute]
    delete_field(key.to_s)
  end
  deleted
end

#fail!(errors = {}) ⇒ Object

Fail the context instance. Failing a context raises an error

that may be rescued by the calling interactor. The context is also flagged
as having failed

Examples:

Fail an interactor context

interactor = MyInteractor.new(name: 'Aaron')
#=> <#MyInteractor name='Aaron'>

interactor.context.fail!
#=> ActiveInteractor::Context::Failure: <#MyInteractor::Context name='Aaron'>

Parameters:

  • errors (ActiveModel::Errors, Hash) (defaults to: {})

    errors to add to the context on failure

Raises:

See Also:

Since:

  • 0.0.1



168
169
170
171
172
# File 'lib/active_interactor/context.rb', line 168

def fail!(errors = {})
  self.errors.merge!(errors) unless errors.empty?
  @_failed = true
  raise Failure, self
end

#failure?Boolean Also known as: fail?

Note:

The #failure? method is the inverse of the #success? method

Whether the context instance has failed. By default, a new context is successful and only changes when explicitly failed

Examples:

Check if a context has failed

context = MyInteractor::Context.new
#=> <#MyInteractor::Context>

context.failure?
false

context.fail!
#=> ActiveInteractor::Context::Failure: <#MyInteractor::Context>

context.failure?
#=> true

Returns:

  • (Boolean)

    ‘false` by default or `true` if failed

Since:

  • 0.0.1



193
194
195
# File 'lib/active_interactor/context.rb', line 193

def failure?
  @_failed || false
end

#keysArray<Symbol>

All keys of properties currently defined on the instance

Examples:

An instance of Context with unknown attribute

MyInteractor::Context.attributes = :first_name, :last_name
#=> [:first_name, :last_name]

context = MyInteractor::Context.new(first_name: 'Aaron', last_name: 'Allen', unknown: 'unknown')
#=> <#MyInteractor::Context first_name='Aaron', last_name='Allen', unknown='unknown'>

context.keys
#=> [:first_name, :last_name, :unknown]

Returns:

  • (Array<Symbol>)

    keys defined on the instance

Since:

  • 0.0.1



211
212
213
# File 'lib/active_interactor/context.rb', line 211

def keys
  each_pair.map { |pair| pair[0].to_sym }
end

#respond_to_missing?(name, include_private) ⇒ Boolean

Attempt to call the interactor for missing validation callback methods

Returns:

  • (Boolean)

    ‘true` if method is a validation callback and exists on the interactor instance

Since:

  • 0.0.1



226
227
228
229
230
# File 'lib/active_interactor/context.rb', line 226

def respond_to_missing?(name, include_private)
  return false unless validation_callback?(name)

  interactor.respond_to?(name, include_private)
end

#rollback!Boolean

Roll back an interactor context. Any interactors to which this context has been passed and which have been successfully called are asked to roll themselves back by invoking their #rollback instance methods.

Examples:

Rollback an interactor’s context

context = MyInteractor.perform(name: 'Aaron')
#=> <#MyInteractor::Context name='Aaron'>

context.rollback!
#=> true

context
#=> <#MyInteractor::Context name='Aaron'>

Returns:

  • (Boolean)

    ‘true` if rolled back successfully or `false` if already rolled back

Since:

  • 0.0.1



249
250
251
252
253
254
# File 'lib/active_interactor/context.rb', line 249

def rollback!
  return false if @_rolled_back

  _called.reverse_each(&:execute_rollback)
  @_rolled_back = true
end

#success?Boolean Also known as: successful?

Note:

the #success? method is the inverse of the #failure? method

Whether the context instance is successful. By default, a new context is successful and only changes when explicitly failed

Examples:

Check if a context has failed

context = MyInteractor::Context.new
#=> <#MyInteractor::Context>

context.success?
true

context.fail!
#=> ActiveInteractor::Context::Failure: <#MyInteractor::Context>

context.success?
#=> false

Returns:

  • (Boolean)

    ‘true` by default or `false` if failed

Since:

  • 0.0.1



275
276
277
# File 'lib/active_interactor/context.rb', line 275

def success?
  !failure?
end