New Plugin: acts_as_state_machine_hacks

Posted by jeff

UPDATE: while this plugin will work for those of you who don’t want to upgrade, there is is a much hipper version of acts_as_state_machine called aasm (that link goes to my fork of it, with the changes listed below incorporated).

Inspired by the evil twin plugin architecture I just made a few small, test-driven tweaks to one of my favorite plugins: acts_as_state_machine

The biggest thing that bugged me about aasm was when you call a method like object.event! it writes to the database, instead of updating the current state, which makes it hard to set a state before validation.

Installation

script/plugin install http://elitists.textdriven.com/svn/plugins/acts_as_state_machine/trunk/
script/plugin install git://github.com/zilkey/acts_as_state_machine_hacks.git

What this plugin does

This plugin hack adds new methods without the exclamation point – it just updates the attribute. So if you have:

1
2
3
4
5
6
7
8
9
  class Conversation < ActiveRecord::Base
    acts_as_state_machine :initial => :open
    state :opened
    state :closed

    event :open do
      transitions :to => :opened,   :from => :closed
    end
  end

ActsAsStateMachine would give you:

1
  conversation.open!

That uses update_attribute under the hood. This plugin adds:

1
  conversation.open

Which just sets state to opened, without touching the database. Suitable for calling before you save, like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  def create
    @conversation = Conversation.new(params[:conversation])
    @conversation.open if params[:conversation][:publish] == "open"
    if @conversation.save
      ...
    else
      ...
    end
  end

  def update
    @conversation = Conversation.find(params[:id])
    @conversation.open if params[:conversation][:publish] == "open"
    if @conversation.update_attributes(params[:conversation]) # => if this doesn't validate, the state column will not have been written
      ...
    else
      ...
    end
  end

I wrote this primarily because I often change state based on fields in the model – like if you check a “published” check box that changes a state from pending to published.

This also allows the possibility of adding a dropdown list to an admin screen where admins can set the status, while maintaining the integrity by still relying on events.

Requirements

You must have the acts_as_state_machine plugin installed. To get the tests to run the acts_as_state_machine directory must be named “acts_as_state_machine”.

Warning

This copies methods directly from acts_as_state_machine. If acts_as_state_machine is updated, this plugin hack will likely break.

For developers

If you want to add your own hacks, you can fork this project on http://github.com/zilkey/acts_as_state_machine_hacks/tree/master

It includes working tests, which can be the hardest part of testing a plugin.

Comments

Leave a response

Comment