Affairs of State
You have an Active Record model. It nees to have multiple states, boolean convenience methods, simple validation, but not complex rules. This gem gives you this in a single line class method.
Installation
Add this line to your application's Gemfile:
gem 'affairs_of_state'
Or install it with:
$ gem install affairs_of_state
Usage
The gem assumes you have a string column named status
on your model:
add_column :model_name, :status, default: "active"
Then you just list your states in the model:
affairs_of_state :active, :inactive
If you'd like to use another column, lets say state
, pass it in as a configuration option:
affairs_of_state :active, :inactive, column: :state
You can scope the helper and scope methods by a prefix:
affairs_of_state :active, :inactive, prefix: :admin
You can also turn off validation:
affairs_of_state :active, :inactive, allow_blank: true
Or give it a long list of statuses:
affairs_of_state :ordered, :cancelled, :shipped, :lost, :in_transit
You can also pass a proc or a method name symbol to the :if option to bypass validation:
affairs_of_state :active, :inactive, if: ->(object) { only_validate_if_this_is_true(object) }
or
affairs_of_state :active, :inactive, if: :only_validate_if_this_method_returns_true
It can be called multiple times per model, provided as each time is with a different column, and that none of the statuses overlap. If either of these are not true it will raise on load.
Methods
The gem provides methods for checking and setting your status. The question mark method returns a boolean, and the bang method changes to that status. Lets assume you have "active" and "cancelled" as defined status:
widget = Widget.first
widget.cancelled! if widget.active?
These methods are scoped by the prefix if one is set:
widget = Widget.first
widget.admin_cancelled! if widget.admin_active?
You can also access all your statuses on the model. If only one is defined it is default, otherwise the column name needs to be passed in:
Widget.statuses # -> ["active", "cancelled"]
Widget.statuses(:status) # -> ["active", "cancelled"]
It also provides scopes automagically, scoped by prefix if one is set:
Widget.active
Widget.cancelled
Widget.admin_active
Widget.admin_cancelled
For select inputs in forms there is a convenience method that returns all states in the format expected by options_for_select
. Again if only one is defined on the model it returns as default, if multiple are defined the column name needs to be passed in:
<%= f.select :status, options_for_select(Widget.statuses_for_select) %>
<%= f.select :status, options_for_select(Widget.statuses_for_select(:status)) %>
"But I want callbacks and validations etc."
Then this gem isn't for you. Consider:
https://github.com/rubyist/aasm
https://github.com/pluginaweek/state_machine
Tests
Just run rspec:
rspec
The usual
By Kevin McPhillips (github@kevinmcphillips.ca)