views:

759

answers:

4

What is the best way to persist the object's state to the database on a transition using aasm? I had thought that this would happen automatically but this doesn't seem to be the case.

(Edit: when I manually save the object, the state column does get updated. But a save isn't done on transitions.)

I can't find much useful documentation for this plugin, so if you have a suggestion for an alternative finite state machine implementation with better documentation, that might help as well.

A: 

I think you have to save in the transition if that's the effect you want. ActiveRecord (which aasm is sitting on top of) doesn't autosave records, by design.

You can do the saving in a callback if you want (and it sounds like you do).

MarkusQ
Thank you, that is what I needed. It seems some days I just can't think of fancy words like 'callback' ;)
Angela
This is unnecessary. All event transitions have a bang method that will automatically persist the record. See my answer for more info.
Ryan McGeary
A: 

I believe AASM will persist the state of the object after transition. See lines 180-189 in aasm/lib/persistence/active_record_persistence.rb

Colin Curtin
+2  A: 

As Colin suggests, AASM will persist your changes for you. What Markus has said is flat out incorrect, except for the fact that the latest version of the gem has a bug.

On line 180 of lib/persistence/active_record_persistence.rb (you can get this by running gem:unpack), you should see the comment, which states:

Writes state to the state column and persists it to the database using update_attribute (which bypasses validation)

However, in the code, it actually calls save instead!

unless self.save

The bug occurs when the underlying model fails validation, because the save method does not bypass validation by default. A quick fix would be to do this instead:

unless self.save(false)

Now, transitions do indeed save the new state to the database.

Jaryl
+3  A: 

If you call the bang! form of the transition event method, the state will persist. For example, say you have an object with the following event:

class Book < ActiveRecord::Base
  # ... 

  aasm_event :close do
    transitions :to => :closed, :from => [:opened]
  end

  # ...
end

Calling book.close will set the state to closed, but will not automatically save. Calling book.close! will set the state *and* automatically save the AR object.

Ryan McGeary