SimplestStatus is a gem built to provide simple, convenient status functionality for Rails models. It's designed to work with any currently-supported version of Rails (tested as far back as 3.0.0) and will work with Ruby 1.9.3 and up.
SimplestStatus is similar to the recently introduced enum
(debuted in Rails 4.1), but is different in that it doesn't rely on a particular version of Rails and it also provides additional functionality like constant-based status lookup, label helpers, and validations.
Add this line to your application's Gemfile:
gem 'simplest_status'
And then execute:
$ bundle
Or install it yourself as:
$ gem install simplest_status
There are two ways to use SimplestStatus, through the default statuses
method or the simple_status
method.
The default assumes you've set up an integer
-type status
field with :null => false
and :default => 0
. For a simple_status
, use the same column-type and settings, just give it the name of your custom status:
class AddStatusToPostsMigration < ActiveRecord::Migration
def change
add_column :posts, :status, :integer, :null => false, :default => 0
add_column :posts, :locale, :integer, :null => false, :default => 0
end
end
Then in your model, extend SimplestStatus
and list out your statuses using statuses
or simple_status
:
class Post < ActiveRecord::Base
extend SimplestStatus
statuses :draft, :preview, :published, :archived
simple_status :locale, [:english, :spanish, :russian]
end
This will generate a number of constants, methods, and model validations.
Post.statuses # => { :draft => 0, :preview => 1, :published => 2, :archived => 3 }
Post.locales # => { :english => 0, :spanish => 1, :russian => 2 }
The returned hash is a StatusCollection
that, when iterated over, yields Status
objects:
Post.statuses.first.tap do |status|
status.name # => :draft
status.value # => 0
status.string # => 'draft'
status.to_hash # => { :draft => 0 }
status.constant_name # => 'DRAFT'
status.label # => 'Draft'
status.for_select # => ['Draft', 0]
end
Post.locales.first.tap do |locale|
locale.name # => :english
locale.value # => 0
locale.string # => 'english'
locale.to_hash # => { :english => 0 }
locale.constant_name # => 'ENGLISH'
locale.label # => 'English'
locale.for_select # => ['English', 0]
end
It also provides a helper method for usage in a form select:
Post.statuses.for_select # => [['Draft', 0], ['Preview', 1], ['Published', 2], ['Archived', 3]]
Post.locales.for_select # => [['English', 0], ['Spanish', 1], ['Russian', 2]]
Instead of referring to status values by the underlying integer, SimplestStatus generates constants for this purpose:
Post::DRAFT # => 0
Post::PREVIEW # => 1
Post::PUBLISHED # => 2
Post::ARCHIVED # => 3
Post::ENGLISH # => 0
Post::SPANISH # => 1
Post::RUSSIAN # => 2
Post.draft
Post.preview
Post.published
Post.archived
Post.english
Post.spanish
Post.russian
Post.new(:status => Post::DRAFT) do |post|
post.draft? # => true
post.preview? # => false
post.published? # => false
post.archived? # => false
end
Post.new(:locale => Post::RUSSIAN) do |post|
post.english? # => false
post.spanish? # => false
post.russian? # => true
end
Post.new(:status => Post::ARCHIVED) do
post.draft # status from Post::ARCHIVED to Post::DRAFT
post.preview # status from Post::DRAFT to Post::PREVIEW
post.published # status from Post::PREVIEW to Post::PUBLISHED
post.archived # status from Post::PUBLISHED to Post::ARCHIVED
end
Post.new(:status => Post::SPANISH) do
post.english # locale from Post::SPANISH to Post::ENGLISH
post.spanish # locale from Post::ENGLISH to Post::SPANISH
post.russian # locale from Post::SPANISH to Post::RUSSIAN
end
Post.new(:status => Post::DRAFT).status_label # => 'Draft'
Post.new(:status => Post::PREVIEW).status_label # => 'Preview'
Post.new(:status => Post::PUBLISHED).status_label # => 'Published'
Post.new(:status => Post::ARCHIVED).status_label # => 'Archived'
Post.new(:locale => Post::ENGLISH).locale_label # => 'English'
Post.new(:locale => Post::SPANISH).locale_label # => 'Spanish'
Post.new(:locale => Post::RUSSIAN).locale_label # => 'Russian'
SimplestStatus will automatically add the following validations:
validates :status, :presence => true, :inclusion => { :in => statuses.values }
validates :locale, :presence => true, :inclusion => { :in => locales.values }
Visit code.viget.com to see more projects from Viget.