vigetlabs/simplest_status

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# SimplestStatus [![Gem Version](https://badge.fury.io/rb/simplest_status.svg)](http://badge.fury.io/rb/simplest_status) [![Code Climate](https://codeclimate.com/github/vigetlabs/simplest_status/badges/gpa.svg)](https://codeclimate.com/github/vigetlabs/simplest_status) [![Test Coverage](https://codeclimate.com/github/vigetlabs/simplest_status/badges/coverage.svg)](https://codeclimate.com/github/vigetlabs/simplest_status/coverage) [![Build Status](https://travis-ci.org/vigetlabs/simplest_status.svg)]((https://travis-ci.org/vigetlabs/simplest_status))

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`](http://api.rubyonrails.org/classes/ActiveRecord/Enum.html) (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.

## Installation
Add this line to your application's Gemfile:

```ruby
gem 'simplest_status'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install simplest_status

## Usage
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:
```ruby
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`:
```ruby
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.

#### Status List
```ruby
Post.statuses # => { :draft => 0, :preview => 1, :published => 2, :archived => 3 }
Post.locales  # => { :english => 0, :spanish => 1, :russian => 2 }
```

The returned hash is a [`StatusCollection`](link) that, when iterated over, yields [`Status`](link) 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:
```ruby
Post.statuses.for_select # => [['Draft', 0], ['Preview', 1], ['Published', 2], ['Archived', 3]]
Post.locales.for_select  # => [['English', 0], ['Spanish', 1], ['Russian', 2]]
```

#### Constants
Instead of referring to status values by the underlying integer, SimplestStatus generates constants for this purpose:
```ruby
Post::DRAFT     # => 0
Post::PREVIEW   # => 1
Post::PUBLISHED # => 2
Post::ARCHIVED  # => 3

Post::ENGLISH   # => 0
Post::SPANISH   # => 1
Post::RUSSIAN   # => 2
```

#### Scopes
```ruby
Post.draft
Post.preview
Post.published
Post.archived

Post.english
Post.spanish
Post.russian
```

#### Predicate Methods
```ruby
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
```

#### Status Mutation Methods
```ruby
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
```

#### Status Label Method
```ruby
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'
```

#### Status Validations
SimplestStatus will automatically add the following validations:
```ruby
validates :status, :presence => true, :inclusion => { :in => statuses.values }
validates :locale, :presence => true, :inclusion => { :in => locales.values }
```

***

<a href="http://code.viget.com">
  <img src="http://code.viget.com/github-banner.png" alt="Code At Viget">
</a>

Visit [code.viget.com](http://code.viget.com) to see more projects from [Viget.](https://viget.com)