gem enumerize の README を翻訳しました

# 概要
gem [enumerize](https://github.com/brainspec/enumerize) の [README](https://github.com/brainspec/enumerize/blob/master/README.md) を翻訳しました。

- 翻訳について
    - 翻訳サービス [Deepl](https://www.deepl.com/translator) と [Goole翻訳](https://translate.google.co.jp/) の訳文を参考にしている箇所があります。
    - 翻訳対象の[コミットハッシュ](https://github.com/brainspec/enumerize/commit/088758fb2294c206da7e288dc0ca30447eb32f77)
    - 非公式の翻訳です。
    - 訳文がおかしい箇所があったら指摘をもらえると幸いです。

- ライセンスについて
    - [enumerize のライセンス](https://github.com/brainspec/enumerize/blob/master/MIT-LICENSE)と同様のライセンスに従います。

# Enumerize

I18n と ActiveRecord/Mongoid/MongoMapper/Sequel のサポートを伴った enum 型の属性

## インストール

Gemfile に下記の行を追加してください。

    gem 'enumerize'

それから下記を実行してください。

    $ bundle

あるいは自身で gem をインストールしてください。

    $ gem install enumerize

## サポートバージョン
- Ruby 2.2+
- Rails 4.2+

## 利用方法

基本

```ruby
class User
  extend Enumerize

  enumerize :sex, in: [:male, :female]
end
```

enum 化された値はただの識別子なので、複数の単語や値を使用したい場合は、`I18n` 機能を使うようにしてください。

ActiveRecord:

```ruby
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :sex
      t.string :role

      t.timestamps
    end
  end
end

class User < ActiveRecord::Base
  extend Enumerize

  enumerize :sex, in: [:male, :female], default: lambda { |user| SexIdentifier.sex_for_name(user.name).to_sym }

  enumerize :role, in: [:user, :admin], default: :user
end
```

:warning: デフォルトでは、`enumerize` はモデルに `inclusion` バリデーションを追加します。`skip_validations` オプションを渡すことでそのバリデーションをスキップできます。:warning:

```ruby
class User < ActiveRecord::Base
  extend Enumerize

  enumerize :sex, in: [:male, :female], skip_validations: lambda { |user| user.new_record? }

  enumerize :role, in: [:user, :admin], skip_validations: true
end
```

Mongoid:

```ruby
class User
  include Mongoid::Document
  extend Enumerize

  field :role
  enumerize :role, in: [:user, :admin], default: :user
end
```

MongoMapper:

```ruby
class User
  include MongoMapper::Document
  extend Enumerize

  key :role
  enumerize :role, in: [:user, :admin], default: :user
end
```

I18n:

```ruby
en:
  enumerize:
    user:
      sex:
        male: "Male"
        female: "Female"
```

`sex` 属性を複数のモデルで使用する場合は、`defaults`　スコープを使用することができます。

```ruby
en:
  enumerize:
    defaults:
      sex:
        male: "Male"
        female: "Female"
```

`i18n_scope` オプションを渡して翻訳を保管するスコープ（あるいはスコープの配列）を指定することもできます。

```ruby
class Person
  extend Enumerize
  extend ActiveModel::Naming

  enumerize :sex, in: %w[male female], i18n_scope: "sex"
  enumerize :color, in: %w[black white], i18n_scope: ["various.colors", "colors"]
end

# ローカリゼーションファイル
en:
  sex:
    male: "Male"
    female: "Female"
  various:
    colors:
      black: "Black"
  colors:
    white: "White"
```

plain Ruby オブジェクトで I18n を使用したい場合は、`ActiveModel::Naming` を extend することを忘れないようにしてください。

```ruby
class User
  extend Enumerize
  extend ActiveModel::Naming
end
```

属性値の取得

```ruby
@user.sex_text # or @user.sex.text
```

enum 化した属性のすべての値の取得

```ruby
User.sex.values # or User.enumerized_attributes[:sex].values
```

enum 化した属性をフォームで使用する（`:only` と `:except` オプションをサポートしています）

```erb
<%= form_for @user do |f| %>
  <%= f.select :sex, User.sex.options %>
<% end %>
```

ブーリアンメソッド

```ruby
user.sex = :male
user.sex.male? #=> true
user.sex.female? #=> false
```

プリディケイトメソッド

```ruby
class User
  extend Enumerize

  enumerize :sex, in: %w(male female), predicates: true
end

user = User.new

user.male?   # => false
user.female? # => false

user.sex = 'male'

user.male?   # => true
user.female? # => false
```

:warning: Mongoid で `enumerize` を使用している場合は、Mongoid によって定義されている名前なので、`writer?` をフィールド値として使用することは推奨しません。:warning:

プレフィックスの使用

```ruby
class User
  extend Enumerize

  enumerize :sex, in: %w(male female), predicates: { prefix: true }
end

user = User.new
user.sex = 'female'
user.sex_female? # => true
```

`:only` と `:except` オプションを使用してどの値にプリディケイトメソッドを作成するかを指定してください。

異なったクラス間で共有された属性を作成するためには、分離したモジュールに属性を定義して、各クラスでそれを include してください。

```ruby
module PersonEnumerations
  extend Enumerize

  enumerize :sex, in: %w[male female]
end

class Person
  include PersonEnumerations
end

class User
  include PersonEnumerations
end
```

カスタム値（たとえば integer）で enum 属性を保存することもできます。`:in` オプションを使用してハッシュを渡してください。

```ruby
class User < ActiveRecord::Base
  extend Enumerize

  enumerize :role, in: {:user => 1, :admin => 2}
end

user = User.new
user.role = :user
user.role #=> 'user'
user.role_value #=> 1

User.role.find_value(:user).value #=> 1
User.role.find_value(:admin).value #=> 2
```

ActiveRecord のスコープ

```ruby
class User < ActiveRecord::Base
  extend Enumerize
  enumerize :sex, :in => [:male, :female], scope: true
  enumerize :status, :in => { active: 1, blocked: 2 }, scope: :having_status
end

User.with_sex(:female)
# SELECT "users".* FROM "users" WHERE "users"."sex" IN ('female')

User.without_sex(:male)
# SELECT "users".* FROM "users" WHERE "users"."sex" NOT IN ('male')

User.having_status(:blocked).with_sex(:male, :female)
# SELECT "users".* FROM "users" WHERE "users"."status" IN (2) AND "users"."sex" IN ('male', 'female')
```

Shallow スコープ

名前を付けたスコープを直接クラスに追加してください。

```ruby
class User < ActiveRecord::Base
  extend Enumerize
  enumerize :sex, :in => [:male, :female], scope: :shallow
  enumerize :status, :in => { active: 1, blocked: 2 }, scope: :shallow
end

User.male
# SELECT "users".* FROM "users" WHERE "users"."sex" = 'male'

User.active
# SELECT "users".* FROM "users" WHERE "users"."status" = 1
```

:warning: `:multiple` オプションを使用したときはスコープを定義することはできません。:warning:

plain Ruby オブジェクトの配列ライクな属性

```ruby
class User
  extend Enumerize

  enumerize :interests, in: [:music, :sports], multiple: true
end

user = User.new
user.interests << :music
user.interests << :sports
```

ActiveRecordの場合

```ruby
class User < ActiveRecord::Base
  extend Enumerize

  serialize :interests, Array
  enumerize :interests, in: [:music, :sports], multiple: true
end
```

すべてのテキスト値の配列を取得

```ruby
@user.interests.texts # shortcut for @user.interests.map(&:text)
```

また、`super` メソッドを使用して enum 属性値を参照することでリーダーメソッドをオーバーライドすることもできます。

```ruby
def sex
  if current_user.admin?
    "Super#{super}"
  else
    super
  end
end
```

### SimpleForm

SimpleForm gem を使用している場合は、input タイプ（デフォルトで`:select`になります）とコレクションを指定する必要はありません。

```erb
<%= simple_form_for @user do |f| %>
  <%= f.input :sex %>
<% end %>
```

ラジオボタンを設定したい場合

```erb
<%= simple_form_for @user do |f| %>
  <%= f.input :sex, :as => :radio_buttons %>
<% end %>
```

Enumerize は SimpleForm の I18n キーを上書きすることに注意してください。enum 属性に関わる input においては SimpleForm のキーの代わりに enum キーが使用されます。これを避けたい場合は、`input` の呼び出しに `:collection` オプションを渡してください。

### Formtastic

Formtastic gem を使用している場合は、input タイプ（デフォルトで`:select`になります）とコレクションを指定する必要はありません。

```erb
<%= semantic_form_for @user do |f| %>
  <%= f.input :sex %>
<% end %>
```

ラジオボタンを設定したい場合

```erb
<%= semantic_form_for @user do |f| %>
  <%= f.input :sex, :as => :radio %>
<% end %>
```

### RSpec

組み込みの Rspec マッチャを使用することもできます。

```ruby
class User
  extend Enumerize

  enumerize :sex, in: [:male, :female]
end

describe User do
  it { should enumerize(:sex) }

  # RSpec3 のシンタックス
  it { is_expected.to enumerize(:sex) }
end
```

#### 修飾子

##### in

`:in` オプションの利用をテストするために `in` 修飾子を使用してください。

```ruby
class User
  extend Enumerize

  enumerize :sex, in: [:male, :female]
end

describe User do
  it { should enumerize(:sex).in(:male, :female) }
end
```

`in` 修飾子を利用することでカスタム値を持つ enum 属性値をテストすることができます。

```ruby
class User
  extend Enumerize

  enumerize :sex, in: { male: 0, female: 1 }
end

describe User do
  it { should enumerize(:sex).in(male: 0, female: 1) }
end
```

##### with_default

`with_default` オプションの利用をテストするために `with_default` 修飾子を使用してください。

```ruby
class User
  extend Enumerize

  enumerize :sex, in: [:male, :female], default: :female
end

describe User do
  it { should enumerize(:sex).in(:male, :female).with_default(:female) }
end
```

##### with_i18n_scope

`with_i18n_scope` オプションの利用をテストするために `with_i18n_scope` 修飾子を使用してください。

```ruby
class User
  extend Enumerize

  enumerize :sex, in: [:male, :female], i18n_scope: 'sex'
end

describe User do
  it { should enumerize(:sex).in(:male, :female).with_i18n_scope('sex') }
end
```

##### with_predicates

`with_predicates` オプションの利用をテストするために `with_predicates` 修飾子を使用してください。

```ruby
class User
  extend Enumerize

  enumerize :sex, in: [:male, :female], predicates: true
end

describe User do
  it { should enumerize(:sex).in(:male, :female).with_predicates(true) }
end
```

`with_predicates` 修飾子を使用することでプレフィックスのある predicate をテストすることができます。

```ruby
class User
  extend Enumerize

  enumerize :sex, in: [:male, :female], predicates: { prefix: true }
end

describe User do
  it { should enumerize(:sex).in(:male, :female).with_predicates(prefix: true) }
end
```

##### with_scope

`:scope` オプションの利用をテストするために `with_scope` 修飾子を使用してください。

```ruby
class User
  extend Enumerize

  enumerize :sex, in: [:male, :female], scope: true
end

describe User do
  it { should enumerize(:sex).in(:male, :female).with_scope(true) }
end
```

`with_scope` 修飾子を使用することでカスタム scope をテストすることができます。

```ruby
class User
  extend Enumerize

  enumerize :sex, in: [:male, :female], scope: :having_sex
end

describe User do
  it { should enumerize(:sex).in(:male, :female).with_scope(scope: :having_sex) }
end
```

##### with_multiple

`:multiple` オプションの利用をテストするために `with_multiple` 修飾子を使用してください。

```ruby
class User
  extend Enumerize

  enumerize :sex, in: [:male, :female], multiple: true
end

describe User do
  it { should enumerize(:sex).in(:male, :female).with_multiple(true) }
end
```

### Shoulda を使用する Minitest

下記の2行を `test_helper.rb` の `class ActiveSupport::TestCase` 定義内に追加することで、shoulda を使用する RSpec マッチャを使用することができます。

```ruby
class ActiveSupport::TestCase
  ActiveRecord::Migration.check_pending!

  require 'enumerize/integrations/rspec'
  extend Enumerize::Integrations::RSpec

  ...
end
```

### その他のライブラリとの統合

Enumerize は自動で下記のライブラリと統合します。

* [RailsAdmin](https://github.com/sferik/rails_admin/)


## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request