ActiveAct is a Rails Engine that introduces a standardized Action layer for your Rails applications. It provides a base class and generators to help you organize business logic in a clean, reusable way.
Add this line to your application's Gemfile:
gem 'active_act'And then execute:
$ bundle installRun the install generator to set up the actions directory:
$ rails generate active_act:installThis will create the app/actions directory. The base class ActiveAct::ApplicationAction is provided by the gem and does not need to be generated in your app.
Create a new action by inheriting from ActiveAct::ApplicationAction:
# app/actions/send_welcome_email.rb
class SendWelcomeEmail < ActiveAct::ApplicationAction
def initialize(user)
@user = user
end
def call
# Your business logic here
UserMailer.welcome(@user).deliver_later
rescue => e
fail(e)
end
endYou can call your action from anywhere in your app:
SendWelcomeEmail.call(user)You can use the built-in generator to quickly scaffold a new action:
rails generate active_act:action ActionNameExample:
rails generate active_act:action SendWelcomeEmailThis will create the file app/actions/send_welcome_email.rb with the following content:
class SendWelcomeEmail < ActiveAct::ApplicationAction
# Uncomment and customize the initializer if needed
# def initialize(args)
# @args = args
# end
def call
# Implement your business logic here
raise NotImplementedError, "You must implement the #call method in SendWelcomeEmail"
end
endThe provided ActiveAct::ApplicationAction includes:
.call(*args, **kwargs, &block): Instantiates and runs the action.#call: To be implemented in your subclass.#fail(error = nil): Raises an error to signal failure.
You can define your action's call method to accept any arguments you need (positional or keyword). For maximum flexibility, use *args, **kwargs:
class OrderProcess < ActiveAct::ApplicationAction
def call(order, user:)
# business logic here
{ order: order, user: user }
end
end
OrderProcess.call(order, user: user)Every call to an action returns an ActionResult object, which provides:
.valueβ the value returned by your action (usually a hash or object).errorβ nil if successful, or the exception if an error occurred.success?β true if no error
Example:
result = OrderProcess.call(order, user: user)
if result.success?
puts result.value # => { order: ..., user: ... }
else
puts "Error: #{result.error}"
endYou can chain actions so that the result of one is passed as the argument to the next:
class NotifyUser < ActiveAct::ApplicationAction
def call(result)
user = result[:user]
# notify user logic
{ notified: true }
end
end
result = OrderProcess.call(order, user: user).then(NotifyUser)
if result.success?
puts "User notified!"
else
puts "Error: #{result.error}"
end- The value returned by the first action is passed as the first argument to the next action's
callmethod. - You can chain as many actions as you want:
ActionA.call(...).then(ActionB).then(ActionC)
# app/actions/process_payment.rb
class ProcessPayment < ActiveAct::ApplicationAction
def initialize(order)
@order = order
end
def call
PaymentService.charge(@order)
rescue PaymentService::Error => e
fail(e)
end
end
# Usage:
ProcessPayment.call(order)Bug reports and pull requests are welcome on GitHub at https://github.com/magdielcardoso/active_act.
- Fork the repository: https://github.com/magdielcardoso/active_act
- Create a new branch for your feature or fix:
git checkout -b my-feature
- Make your changes, including tests if applicable.
- Run the test suite to ensure everything is working:
bundle install bundle exec rake spec - Commit your changes and push your branch:
git add . git commit -m "Describe your change" git push origin my-feature
- Open a Pull Request on GitHub and describe your contribution.
Thank you for helping to improve ActiveAct!
The gem is available as open source under the terms of the MIT License.