public
Description: Adds the ability to call events that change the state without writing to the database
Homepage: http://acts_as_state_machine_hacks.zilkey.com/
Clone URL: git://github.com/zilkey/acts_as_state_machine_hacks.git
100644 72 lines (48 sloc) 2.568 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
= Acts As State Machine Hacks
 
I dig acts_as_state_machine (http://elitists.textdriven.com/svn/plugins/acts_as_state_machine/trunk/) and use it in almost all of my apps. The biggest thing that bugged me 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:
 
  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:
 
  conversation.open!
  
That uses update_attribute under the hood. This plugin adds:
 
  conversation.open
  
Which just sets state to opened, without touching the database. Suitable for calling before you save, like:
 
  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 and 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.