README.md in rails_attr_enum-0.1.0 vs README.md in rails_attr_enum-0.1.1

- old
+ new

@@ -1,170 +1,230 @@ # RailsAttrEnum -## Enums for Rails models -I created RailsAttrEnum as a way to create an enum-like structure similar to -enums in C languages. You can specify the accepted identifiers for the possible -integer values for the model's attribute as well have built-in validation to -ensure only the values are accepted. +Enums for Rails attributes. Specify enumeration identifiers for int attributes +on your Rails models. Includes constants for your identifiers, validation, +model class scopes, and instance helper methods. -### Usage +## Build Status +[![Build Status](https://travis-ci.org/jfairbank/rails_attr_enum.png?branch=master)](https://travis-ci.org/jfairbank/rails_attr_enum) -Here's an example given a class `User` with an attribute `role`: +## Installation +Add to your Gemfile: - # Example model User for a blog app - class User < ActiveRecord::Base - extend RailsAttrEnum +```ruby +gem 'rails_attr_enum' +``` - attr_enum :role, :admin, :editor, :author, :user - end +And then run bundler: - # Creates module `User::Role` with constants for each possible value - User::Role::ADMIN == 0 - User::Role::EDITOR == 1 - User::Role::AUTHOR == 2 - User::Role::USER == 3 + $ bundle install +## Usage + +Here's an example given a class `User` with an attribute `role`: + +```ruby +# Example model User for a blog app +class User < ActiveRecord::Base + extend RailsAttrEnum + attr_enum :role, :admin, :editor, :author, :user +end + +# Creates module `User::Role` with constants for each possible value +User::Role::ADMIN == 0 +User::Role::EDITOR == 1 +User::Role::AUTHOR == 2 +User::Role::USER == 3 +``` + [View other ways to define and customize enums](https://github.com/jfairbank/rails_attr_enum/wiki/Adding-an-Enum-to-a-Model) -### Helpers for Model Instances +## Helpers for Model Instances A couple helpers methods are added to the model and the enum attribute. Get the "display" label for the current value with the `display_*` method: - user = User.new(User::Role::ADMIN) - user.display_role == 'Admin' +```ruby +user = User.new(role: User::Role::ADMIN) +user.display_role == 'Admin' +``` You can check for a specific value with a query `*?` method: - user = User.new(User::Role::AUTHOR) - user.role.admin? # false - user.role.editor? # false - user.role.author? # true - user.role.user? # false +```ruby +user = User.new(role: User::Role::AUTHOR) +user.role.admin? # false +user.role.editor? # false +user.role.author? # true +user.role.user? # false +``` The query method works via a forwarding class, so the normal `role` and `role=` methods should work as expected. **NOTE**: one caveat to this is if you try to use a hash map of the enum values to some other value. See below: - alt_label_map = { - User::Role::ADMIN => 'The admin user', - User::Role::EDITOR => 'An editor', - User::Role::AUTHOR => 'An author', - User::Role::USER => 'A user' - } +```ruby +alt_label_map = { + User::Role::ADMIN => 'The admin user', + User::Role::EDITOR => 'An editor', + User::Role::AUTHOR => 'An author', + User::Role::USER => 'A user' +} - user = User.new(User::Role::EDITOR) - alt_label = alt_label_map[user.role] - alt_label == nil # not 'An editor' +user = User.new(role: User::Role::EDITOR) +alt_label = alt_label_map[user.role] +alt_label == nil # not 'An editor' +``` -If you want the hash to work as expected than call the `.value` method on the +If you want the hash to work as expected then call the `.value` method on the attribute: - alt_label = alt_label_map[user.role.value] - alt_label == 'An editor' +```ruby +alt_label = alt_label_map[user.role.value] +alt_label == 'An editor' +``` Thus, the `.value` method on the attribute gives the actual `Fixnum` value. There is also a `.key` method which gives the symbol key: - user = User.new(User::Role::ADMIN) - user.role.key == :admin +```ruby +user = User.new(role: User::Role::ADMIN) +user.role.key == :admin +``` The attribute value can also be set with a bang `*!` method - user = User.new - user.role.user! - user.display_role == 'User' +```ruby +user = User.new +user.role.user! +user.display_role == 'User' - user.role.author! - user.display_role == 'Author' +user.role.author! +user.display_role == 'Author' +``` -### Scopes for Models +## Scopes for Models Convenient scopes are created for each possible enum value on the model class: - User.scope_admin == User.where(role: User::Role::ADMIN) - User.scope_editor == User.where(role: User::Role::EDITOR) - User.scope_author == User.where(role: User::Role::AUTHOR) - User.scope_user == User.where(role: User::Role::USER) +```ruby +User.scope_admin == User.where(role: User::Role::ADMIN) +User.scope_editor == User.where(role: User::Role::EDITOR) +User.scope_author == User.where(role: User::Role::AUTHOR) +User.scope_user == User.where(role: User::Role::USER) +``` -### Enum Helper Methods +## Enum Helper Methods Helper methods are added to the actual `Enum` module as well. -`get_label` and `get_key` get the (surprise!) label and key for a given enum +### get_label and get_key +Get the (surprise!) label and key for a given enum value: - User::Role.get_label(User::Role::ADMIN) == 'Admin' - User::Role.get_key(User::Role::USER) == :user +```ruby +User::Role.get_label(User::Role::ADMIN) == 'Admin' +User::Role.get_key(User::Role::USER) == :user +``` ---- +### attr_name +Return the attribute name as a symbol -`attr_name` returns the attribute symbol +```ruby +User::Role.attr_name == :role +``` - User::Role.attr_name == :role +### keys +Return all the enum keys ---- +```ruby +User::Role.keys == [:admin, :editor, :author, :user] +``` -`keys` returns all the enum keys +### values +Return all the enum values - User::Role.keys == [:admin, :editor, :author, :user] +```ruby +User::Role.values == [0, 1, 2, 3] +``` ---- +### labels +Return all the enum labels -`values` returns all the enum values +```ruby +User::Role.labels == ['Admin', 'Editor', 'Author', 'User'] +``` - User::Role.values == [0, 1, 2, 3] - ---- - -`labels` returns all the enum labels - - User::Role.labels == ['Admin', 'Editor', 'Author', 'User'] - ---- - -`label_value_pairs` returns an array of pairs of the label and value for each +### label_value_pairs +Return an array of pairs of the label and value for each enum value. This is mainly a convenience method for something like the collection option for a select input in the [Formtastic](https://github.com/justinfrench/formtastic) or -[ActiveAdmin (which uses Formtastic)](https://github.com/gregbell/active_admin) -gems: +[ActiveAdmin](https://github.com/gregbell/active_admin) (which uses Formtastic) +gems, so you can easily generate select options: - User::Role.label_value_pairs == - [['Admin', 0], ['Editor', 1], ['Author', 2], ['User', 3]] +```ruby +User::Role.label_value_pairs == [ + ['Admin', 0], ['Editor', 1], ['Author', 2], ['User', 3] +] ---- +# In an ActiveAdmin form +ActiveAdmin.register User do + form do |f| + f.inputs 'User Details' do + f.input :first_name + f.input :last_name + f.input :email + # Example usage of `label_value_pairs` + f.input :role, as: :select, collection: User::Role.label_value_pairs + end + end +end +``` + +You can also filter the results by passing in enum value keys as symbol +arguments: + +```ruby +User::Role.label_value_pairs(:admin, :author) == [ + ['Admin', 0], ['Author', 2] +] +``` + +### to_h and to_json `to_h` and `to_json` return a hash and a json string representation of the enum, respectively. They both offer an `only` and an `except` option to specify if you only want the value or maybe only the label and key or if you want everything but key. **NOTE**: passing only key to `only` or excluding all but one key via `except` will give that single value (whether it's value, key, or label) instead of a hash. See below to understand: - # Default call with no options - User::Role.to_h == { - 'ADMIN' => { key: :admin, label: 'Admin', value: 0 }, - 'EDITOR' => { key: :editor, label: 'Editor', value: 1 }, - 'AUTHOR' => { key: :author, label: 'Author', value: 2 }, - 'USER' => { key: :user, label: 'User', value: 3 } - } +```ruby +# Default call with no options +User::Role.to_h == { + 'ADMIN' => { key: :admin, label: 'Admin', value: 0 }, + 'EDITOR' => { key: :editor, label: 'Editor', value: 1 }, + 'AUTHOR' => { key: :author, label: 'Author', value: 2 }, + 'USER' => { key: :user, label: 'User', value: 3 } +} - # Call with a single symbol (would also work with `only: [:value]`) - # Notice the mapped values are not hashes like above because we only - # specified that we wanted the value - User::Role.to_h(only: :value) == { - 'ADMIN' => 0, - 'EDITOR' => 1, - 'AUTHOR' => 2, - 'USER' => 3 - } +# Call with a single symbol (would also work with `only: [:value]`) +# Notice the mapped values are not hashes like above because we only +# specified that we wanted the value +User::Role.to_h(only: :value) == { + 'ADMIN' => 0, + 'EDITOR' => 1, + 'AUTHOR' => 2, + 'USER' => 3 +} - # Would also work with `except: [:value]` - User::Role.to_json(except: :value) == - "{\"ADMIN\":{\"key\":\"admin\",\"label\":\"Admin\"},\"EDITOR\":{\"key\":\"editor\",\"label\":\"Editor\"},\"AUTHOR\":{\"key\":\"author\",\"label\":\"Author\"},\"USER\":{\"key\":\"user\",\"label\":\"User\"}}" +# Would also work with `except: [:value]` +User::Role.to_json(except: :value) == + "{\"ADMIN\":{\"key\":\"admin\",\"label\":\"Admin\"},\"EDITOR\":{\"key\":\"editor\",\"label\":\"Editor\"},\"AUTHOR\":{\"key\":\"author\",\"label\":\"Author\"},\"USER\":{\"key\":\"user\",\"label\":\"User\"}}" +``` -### Feedback and Pull Requests Welcome +## Feedback and Pull Requests Welcome This is my first real Rails gem, so I welcome all feedback and ideas. I hope this gem is as helpful to you as it has been to me in my own projects.