0.0
No release in over 3 years
Low commit activity in last 3 years
A convention-based state machine that complements your models without stealing the show
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.16
>= 0
~> 10.0
~> 3.7

Runtime

 Project Readme

Transitionable

A convention-based state machine that complements your models without stealing the show.

Multiple state machines are supported.

Installation

Add this line to your application's Gemfile:

gem 'transitionable'

And then execute:

$ bundle

Usage

Single state machine in model

class Event

  # By default, Transitionable assumes including class defines the following constants BEFORE including this module:
  #
  #  * STATES
  #  * TRANSITIONS

  STATES = {
    STAGED:    'staged',
    STARTED:   'started',
    COMPLETED: 'completed'
  }.freeze

  TRANSITIONS = [
    { from: STATES[:STAGED], to: STATES[:STARTED] },
    { from: STATES[:STARTED], to: STATES[:COMPLETED] }
  ].freeze

  include Transitionable

  # specifies the column that needs to be transitioned
  transition :some_state

end

Provides the following helpers

event.staged?
event.started?
event.completed?

Provides 2 validation methods

event.validate_transition(target_state: 'new_state')
# => returns true or false

event.validate_transition!(target_state: 'new_state')
# => returns true or raises Transitionable::InvalidStateTransition exception

Multiple state machines in model

class Event

  DELIVERY_STATES = {
    STAGED:    'staged',
    STARTED:   'started',
    COMPLETED: 'completed'
  }.freeze

  PREP_STATES = {
    COOKING: 'cooking',
    COOKED:  'cooked'
  }.freeze

  DELIVERY_TRANSITIONS = [
    { from: DELIVERY_STATES[:STAGED], to: DELIVERY_STATES[:STARTED] },
    { from: DELIVERY_STATES[:STARTED], to: DELIVERY_STATES[:COMPLETED] }
  ].freeze

  PREP_TRANSITIONS = [
    { from: PREP_STATES[:COOKING], to: PREP_STATES[:COOKED] }
  ]

  include Transitionable

  transition :delivery_state, DELIVERY_STATES, DELIVERY_TRANSITIONS
  transition :prep_state, PREP_STATES, PREP_TRANSITIONS

end

Provides the following helpers

event.staged?
event.started?
event.completed?
event.cooking?
event.cooked?

Provides 2 validation methods

event.validate_transition(target_state: 'new_state')
# => returns true or false

# optionally, validate_transition also yield an error object when transition is invalid.
event.validate_transition(target_state: 'new_state') do |error|
  # You can do things like:
  Airbrake.notify(error, attributes) # sends the error along with including model's attributes
end

event.validate_transition!(target_state: 'new_state')
# => returns true or raises Transitionable::InvalidStateTransition exception

Important assumptions with multiple state machines:

  • Each state must be unique across all state machines in the model. Otherwise, InvalidStateTransition exception will thrown as Transitionable attempts to define the same helper method multiple times.
  • For the same reason, "#{state}?" must not be defined in your model for each of your state.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/transitionable.

License

The gem is available as open source under the terms of the MIT License.