Kamil Baćkowski
Library for adding finite state machines to Ruby classes.
class Job
include AASM
aasm do
state :sleeping, :initial => true
state :running, :cleaning
event :run do
transitions :from => :sleeping, :to => :running
end
event :clean do
transitions :from => :running, :to => :cleaning
end
end
end
class Account < ApplicationRecord
enum state: { step1: 'step1', step2: 'step2',
step3: 'step3', finished: 'finished' }
end
Service object
class AccountManager
include AASM, ActiveModel::Model
attr_accessor :account, :name, :country, :language
validates :name, presence: true, if: :step1?
validates :country, presence: true, if: :step2?
validates :language, presence: true, if: :step3?
aasm do
state :step1, initial: true
state :step2, :step3, :finished
after_all_transitions :update_account_state
event :next_step do
transitions from: :step1, to: :step2
transitions from: :step2, to: :step3
transitions from: :step3, to: :finished
end
end
def initialize(attributes = {})
super
aasm_write_state_without_persistence(account.state.to_sym)
end
def save
if valid?
account.update! send(STEP_AVAILABLE_VALUES.fetch(aasm.current_state))
else
false
end
end
private
def update_account_state
account.update_column(:state, aasm.to_state)
end
end
class AccountsController < ApplicationController
def new
@account = Account.new
end
def edit
@account = Account.find(params[:id])
end
def create
@account = Account.new
account_manager = AccountManager.new(account_params.merge(account: @account))
redirect_to edit_account_path(@account) if account_manager.save && account_manager.next_step
end
def update
@account = Account.find(params[:id])
account_manager = AccountManager.new(account_params.merge(account: @account))
redirect_to edit_account_path(@account) if account_manager.save && account_manager.next_step
end
private
def account_params
params.require(:account).permit(:name, :country, :language)
end
end
Always use aasm oustide of ActiveRecord models.
Questions ?