-
-
Notifications
You must be signed in to change notification settings - Fork 12
Callbacks
ActiveInteractor uses ActiveModel::Callbacks and ActiveModel::Validations::Callbacks on context validation, #perform, and #rollback. Callbacks can be defined with a Proc, or Symbol method name and take the same conditional arguments outlined in those two modules.
We can do work before an interactor's context is validated with the .before_context_validation method:
class MyInteractorContext < ActiveInteractor::Context::Base
attributes :first_name, :last_name, :email
validates :last_name, presence: true
end
class MyInteractor < ActiveInteractor::Base
before_context_validation { context.last_name ||= 'Unknown' }
end
result = MyInteractor.perform(first_name: 'Aaron', email: 'hello@aaronmallen.me')
result.valid?
#=> true
result.last_name
#=> 'Unknown'
We can do work after an interactor's context is validated with the .after_context_validation method:
class MyInteractorContext < ActiveInteractor::Context::Base
attributes :first_name, :last_name, :email
validates :email, presence: true,
format: { with: URI::MailTo::EMAIL_REGEXP }
end
class MyInteractor < ActiveInteractor::Base
after_context_validation { context.email&.downcase! }
end
result = MyInteractor.perform(first_name: 'Aaron', last_name: 'Allen', email: 'HELLO@AARONMALLEN.ME')
result.valid?
#=> true
result.email
#=> 'hello@aaronmallen.me'
We can do work before #perform is invoked with the .before_perform method:
class MyInteractor < ActiveInteractor::Base
before_perform :print_start
def perform
puts 'Performing'
end
private
def print_start
puts 'Start'
end
end
MyInteractor.perform
"Start"
"Performing"
#=> <#MyInteractor::Context...>
We can do work around #perform invokation with the .around_perform method:
class MyInteractor < ActiveInteractor::Base
around_perform :track_time
def perform
sleep(1)
end
private
def track_time
context.start_time = Time.now.utc
yield
context.end_time = Time.now.utc
end
end
result = MyInteractor.perform
result.start_time #=> 2019-01-01 00:00:00 UTC
result.end_time #=> 2019-01-01 00:00:01 UTC
We can do work after #perform is invoked with the .after_perform method:
class MyInteractor < ActiveInteractor::Base
after_perform :print_done
def perform
puts 'Performing'
end
private
def print_done
puts 'Done'
end
end
MyInteractor.perform
"Performing"
"Done"
#=> <#MyInteractor::Context...>
We can do work before #rollback is invoked with the .before_rollback method:
class MyInteractor < ActiveInteractor::Base
before_rollback :print_start
def perform
context.fail!
end
def rollback
puts 'Rolling Back'
end
private
def print_start
puts 'Start'
end
end
MyInteractor.perform
"Start"
"Rolling Back"
#=> <#MyInteractor::Context...>
We can do work around #rollback invokation with the .around_rollback method:
class MyInteractor < ActiveInteractor::Base
around_rollback :track_time
def perform
context.fail!
end
def rollback
sleep(1)
end
private
def track_time
context.start_time = Time.now.utc
yield
context.end_time = Time.now.utc
end
end
result = MyInteractor.perform
result.start_time
#=> 2019-01-01 00:00:00 UTC
result.end_time
#=> 2019-01-01 00:00:01 UTC
We can do work after #rollback is invoked with the .after_rollback method:
class MyInteractor < ActiveInteractor::Base
after_rollback :print_done
def perform
context.fail!
end
def rollback
puts 'Rolling Back'
end
private
def print_done
puts 'Done'
end
end
MyInteractor.perform
"Rolling Back"
"Done"
#=> <#MyInteractor::Context...>
We can do worker before #perform is invoked on each interactor in an organizer with the .before_each_perform method:
class MyInteractor1 < ActiveInteractor::Base
def perform
puts 'MyInteractor1'
end
end
class MyInteractor2 < ActiveInteractor::Base
def perform
puts 'MyInteractor2'
end
end
class MyOrganizer < ActiveInteractor::Organizer::Base
before_each_perform :print_start
organized MyInteractor1, MyInteractor2
private
def print_start
puts "Start"
end
end
MyOrganizer.perform
"Start"
"MyInteractor1"
"Start"
"MyInteractor2"
#=> <MyOrganizer::Context...>
We can do worker around #perform invokation on each interactor in an organizer with the .around_each_perform method:
class MyInteractor1 < ActiveInteractor::Base
def perform
puts 'MyInteractor1'
sleep(1)
end
end
class MyInteractor2 < ActiveInteractor::Base
def perform
puts 'MyInteractor2'
sleep(1)
end
end
class MyOrganizer < ActiveInteractor::Organizer::Base
around_each_perform :print_time
organized MyInteractor1, MyInteractor2
private
def print_time
puts Time.now.utc
yield
puts Time.now.utc
end
end
MyOrganizer.perform
"2019-01-01 00:00:00 UTC"
"MyInteractor1"
"2019-01-01 00:00:01 UTC"
"2019-01-01 00:00:01 UTC"
"MyInteractor2"
"2019-01-01 00:00:02 UTC"
#=> <MyOrganizer::Context...>
We can do worker after #perform is invoked on each interactor in an organizer with the .after_each_perform method:
class MyInteractor1 < ActiveInteractor::Base
def perform
puts 'MyInteractor1'
end
end
class MyInteractor2 < ActiveInteractor::Base
def perform
puts 'MyInteractor2'
end
end
class MyOrganizer < ActiveInteractor::Organizer::Base
after_each_perform :print_done
organized MyInteractor1, MyInteractor2
private
def print_done
puts "Done"
end
end
MyOrganizer.perform
"MyInteractor1"
"Done"
"MyInteractor2"
"Done"
#=> <MyOrganizer::Context...>