I have recently begun using several Rails plugins after having coded many things by hand. I think its better when you code everything by hand in the beginning but after some time it will be inevitable that you use others' plugins. Anyway, one plugin that I have reasonably struggled to understand is acts_as_state_machine plugin. What it does is, it provides your models with a state. That is, they become stateful. The state itself is of course stored in the database table with column called 'state'. The plugin provides you with simple methods for setting transitions and querying states. Although very useful, it has some quirks of its own.

One thing is that when you create a new object with Class.new, you do not get state property immediately. It's only after you save the object that the state is set. So you can use 'create' method to create and save the object with its state property. Another solution to this problem is setting the default 'state' through migration files. But this has other problems of its own. When you set state through migrations or simply through object.state = 'some_state' then you will lose this state data when it is saved to the database. The 'state' property when the object is saved to the database is then set to the initial state defined in the model. Here are some examples for clarity, build on the code from Aizat's blog (excellent read by the way):


class Person < initial =""> :sleeping
state :sleeping
state :showering
state :working
state :dating

event :shower do
transitions :from => :sleeping, :to => :showering
transitions :from => :working, :to => :showering
transitions :from => :dating, :to => :showering
end

event :work do
transitions :from => :showering, :to => :working
# Going to work before showering? Stinky.
transitions :from => :sleeping, :to => :working
end

event :date do
transitions :from => :showering, :to => :dating
end

event :sleep do
transitions :from => :showering, :to => :sleeping
transitions :from => :working, :to => :sleeping
transitions :from => :dating, :to => :sleeping
end
end

>> person = Person.new
=> #<Person id: nil, state: nil, created_at: nil, updated_at: nil>
>> person.shower!
NoMethodError: You have a nil object when you didn't expect it!

But, here's something interesting:

>> person.state = 'working'
=> "working"
>> person
=> #<Person id: nil, state: "working", created_at: nil, updated_at: nil>
>> person.shower!
=> true
>> person
=> #<Person id: 3, state: "sleeping", created_at: "2008-03-11 15:04:41", updated_at: "2008-03-11 15:04:41">

It's still sleeping in the end! What I understand is that it doesn't matter what you do until the record is saved. It will still be initialized like it is defined no matter what events you call before.
You have to understand how callbacks are called to understand this example.

Have a nice day.