How to integrate AASM (ActsAsStateMachine) in Ruby on Rails


Ruby on Rails provides a powerful framework for building web applications, and one essential aspect of many applications is managing the state of objects. AASM, or ActsAsStateMachine, is a Ruby library that makes it seamless to implement state machines in our Rails models. In this answer, we will explore the process of integrating AASM into our Ruby on Rails application and demonstrate how it can simplify state management.

Note: A sample application is provided in the demo example at the end of this Answer.

Installation

To get started, we add the AASM gem to our Rails application by including it in our Gemfile:

gem 'aasm'
Adding the aasm gem to ./Gemfile

Then, we run bundle install in our terminal.

Usage

Let’s illustrate the integration process by considering a common scenario: managing the state of resumes in a job application system. Assume we have a Resume model, and we want to track whether a resume is pending, accepted, or rejected.

1. Generating a migration

We start by generating a migration to add a state column to the resumes table:

rails generate migration AddStateToResumes state:string
Adding a state column to the resumes table

We run the migration using the following command:

rails db:migrate
Run the pending migration

2. Including AASM in the model

We open the Resume model (usually located in ./app/models/resume.rb) and include AASM:

class Resume < ApplicationRecord
include AASM
aasm column: 'state' do
state :pending, initial: true
state :accepted
state :rejected
event :accept do
transitions from: :pending, to: :accepted
end
event :reject do
transitions from: :pending, to: :rejected
end
end
end

In this example, we define three states (pending, accepted, and rejected) and two events (accept and reject) to transition between them.

3. Handling states in the controller

We add the following two new actions to the ResumesController (usually located in ./app/controllers/resumes_controller.rb):

  • accept: To handle the functionality if the resume is accepted.

  • reject: To handle the functionality if the resume is rejected.

These actions look like the following:

def accept
@resume = Resume.find(params[:id])
@resume.accept!
redirect_to resumes_path
end
def reject
@resume = Resume.find(params[:id])
@resume.reject!
redirect_to resumes_path
end
The accept and reject methods in ResumesController

4. Updating the view

Let’s update the views to display resumes and allow state transitions using buttons. In the ./app/views/resumes/index.html.erb file, we include the following code:

<div class="container">
<h1>Resumes</h1>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>State</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% @resumes.each do |resume| %>
<tr>
<td><%= resume.name %></td>
<td><%= resume.state %></td>
<td>
<% if resume.pending? %>
<%= button_to 'Accept', accept_resume_path(resume), method: :put, class: 'btn btn-success' %>
<%= button_to 'Reject', reject_resume_path(resume), method: :put, class: 'btn btn-danger' %>
<% else %>
No action required!
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= link_to 'New Resume', new_resume_path, class: 'btn btn-primary' %>
</div>

Assuming we have already added Bootstrap to the application, the above-mentioned code will display the resumes in the form of a table with two buttons, “Accept” and “Reject,” for each resume to change its state.

5. Adding routes for the states

Lastly, we’ll add some routes to our application to handle the accept and reject actions. We add the following code to the config/routes.rb file in the Rails.application.routes.draw block:

resources :resumes do
member do
put :accept
put :reject
end
end
Adding routes for accept and reject

Conclusion

Integrating AASM into our Ruby on Rails application provides an elegant solution for managing the state of our models. By defining states and transitions, we can bring clarity and structure to complex workflows. AASM’s straightforward syntax and seamless integration with Rails make it a valuable tool for developers working on applications with dynamic state requirements.

In summary, AASM simplifies state management in Ruby on Rails, allowing us to focus on building robust and maintainable applications. By incorporating AASM into our project, we empower our models with a powerful state machine that enhances the overall flexibility and efficiency of our application.

Demo example

Go through the demo application provided below. Start the Rails server by clicking the “Run” button. By default, the /resumes page is visible on the output. You can also view your application by clicking on the link provided next to “Your app can be found at:”.

Click the “New Resume” button, provide a name in the form, and click the “Create Resume” button. After successfully creating the resume, click the “Back to resumes” button. It’ll display the “Accept” and “Reject” buttons with that particular resume.

Click any of the buttons to transition its state.

Note: You might need to refresh the page to see the updated changes.

# This file is used by Rack-based servers to start the application.

require_relative "config/environment"

run Rails.application
Rails.application.load_server
Demo application
Copyright ©2024 Educative, Inc. All rights reserved