README.md in simple_states-0.1.0.pre2 vs README.md in simple_states-0.1.0.pre3

- old
+ new

@@ -5,70 +5,76 @@ ## Usage Define states and events like this: - class Foo - include SimpleStates +``` ruby +class Foo + include SimpleStates - states :created, :started, :finished + states :created, :started, :finished - event :start, :from => :created, :to => :started, :if => :startable? - event :finish, :to => :finished, :after => :cleanup + event :start, :from => :created, :to => :started, :if => :startable? + event :finish, :to => :finished, :after => :cleanup - attr_accessor :state, :started_at, :finished_at + attr_accessor :state, :started_at, :finished_at - def start - # start foo - end + def start + # start foo + end - def startable? - true - end + def startable? + true + end - def cleanup - # cleanup foo - end - end + def cleanup + # cleanup foo + end +end +``` Including the SimpleStates module to your class is currently required. We'll add hooks for ActiveRecord etc later. SimpleStates expects your model to support attribute accessors for `:state`. Event options have the following well-known meanings: - :from # valid states to transition from - :to # target state to transition to - :if # only proceed if the given method returns true - :unless # only proceed if the given method returns false - :before # run the given method before running `super` and setting the new state - :after # run the given method at the very end +``` ruby +:from # valid states to transition from +:to # target state to transition to +:if # only proceed if the given method returns true +:unless # only proceed if the given method returns false +:before # run the given method before running `super` and setting the new state +:after # run the given method at the very end +``` All of these options except for `:to` can be given as a single symbol or string or as an Array of symbols or strings. Calling `event` will effectively add methods to a proxy module which is included to the singleton class of your class' instances. E.g. declaring `event -:start` in the example above will add a method `start` to a module included to -the singleton class of instances of `Foo`. +:start` in the example above will add methods `start` and `start!` to a module +included to the singleton class of instances of `Foo`. This method will -1. check if `:if`/`:except` conditions apply (if given) and just return from the method otherwise +1. check if `:if`/`:unless` conditions apply (if given) and just return from the method otherwise 2. check if the object currently is in a valid `:from` state (if given) and raise an exception otherwise 3. run `:before` callbacks (if given) 4. call `super` if Foo defines the current method (i.e. call `start` but not `finish` in the example above) 5. add the object's current state to its `past_states` history 6. set the object's `state` to the target state given as `:to` 7. set the object's `[state]_at` attribute to `Time.now` if the object defines a writer for it 8. run `:after` callbacks (if given) You can define options for all events like so: - event :finish, :to => :finished, :after => :cleanup - event :all, :after => :notify +``` ruby +event :finish, :to => :finished, :after => :cleanup +event :all, :after => :notify +``` This will call :cleanup first and then :notify on :finish. If no target state was given for an event then SimpleStates will try to derive it from the states list. I.e. for an event `start` it will check the states @@ -76,33 +82,38 @@ way then it will raise an exception. By default SimpleStates will assum `:created` as an initial state. You can overwrite this using: - self.initial_state :something +``` ruby +# note that we have to use self here! +self.initial_state = :some_state +``` So with the example above something the following would work: - foo = Foo.new +``` ruby +foo = Foo.new - foo.state # :created - foo.created? # true - foo.was_created? # true - foo.state?(:created) # true +foo.state # :created +foo.created? # true +foo.was_created? # true +foo.state?(:created) # true - foo.start # checks Foo#startable? and then calls Foo#start +foo.start # checks Foo#startable? and then calls Foo#start +# calling foo.start! (with exclamation mark) would perform same actions as foo.start, but +# also call foo.save! afterwards. - foo.state # :started - foo.started? # true - foo.started_at # Time.now - foo.created? # false - foo.was_created? # true +foo.state # :started +foo.started? # true +foo.started_at # Time.now +foo.created? # false +foo.was_created? # true - foo.finish # just performs state logic as there's no Foo#finish +foo.finish # just performs state logic as there's no Foo#finish - foo.state # :finished - foo.finished? # true - foo.finished_at # Time.now - foo.was_created? # true - foo.was_started? # true - - +foo.state # :finished +foo.finished? # true +foo.finished_at # Time.now +foo.was_created? # true +foo.was_started? # true +```