SolidState
Minuscule but solid state machine for Ruby classes. The only dependency is that your model responds to a getter and setter for state.
# simplest example, using just an accessor
class Post
include SolidState
attr_accessor :state
states :draft, :published
end
# in its simplest form you just declare the possible states.
# if it's a simple class you just get boolean methods for checking
# whether the current status is X or Y.
p = Post.new
p.state # => 'draft'
p.draft? # true
p.published? # => false
p.state = 'published'
p.published? # => true
# now, if the model class responds to validates_inclusion_of, it will
# mark the record invalid if an unknown state is set.
# let's assume this is actually an ActiveRecord class, and the
# table contains a column named 'state'.
class Post < ActiveRecord::Base
include SolidState
states :draft, :published
end
p = Post.new
p.state = 'published'
p.valid? # => true
p.state = 'deleted'
p.valid? # => false
# ok, now let's gets get fancier. we're going to declare transitions
# which will govern the possible directions in which an object's state
# can move to.
class Subscriber < ActiveRecord::Base
include SolidState
states :inactive, :active, :unsubscribed, :disabled do
transitions :from => :inactive, :to => :active
transitions :from => :active, :to => [:unsubscribed, :disabled]
transitions :from => :unsubscribed, :to => :active
end
end
s = Subscriber.new
s.state # => 'inactive'
# since we declared transitions, we can now call #{state}! which
# checks whether the instance can transition to that state and
# if so, sets the new state and optionally saves the record.
s.active! # => true
s.inactive! # => raises InvalidTransitionError
# this also works outside transition methods, of course.
s.reload # => true
s.active? # => true
s.state = 'inactive'
s.valid? # => false
# the last trick this library does is that it optionally lets you
# declare callback methods that are called whenever a transition
# method succeeds. just define a method called #once_[state] in
# your model.
class Subscriber
def once_unsubscribed
puts "Sorry to see you go!"
end
end
# ...
s.unsubscribed! # => prints "Sorry to see you go!"
That's about it. For examples check the examples directory in this repo.
Contributions
You're more than welcome. Send a pull request, including tests, and make sure you don't break anything. That's it.
Author
Tomás Pollak
Copyright
(c) Fork Limited. MIT license.