[Rails]ActiveHashの使用例（備忘録）

# ActiveHash(アクティブハッシュ)
**ActiveHash**とは、モデルファイル内に直接記述することで、データベースへ保存せずにデータを取り扱うことができるGemです。  
モデルファイルに直接記述したデータに対して、ActiveRecordのようなメソッドを用いることができます。  
例えば、都道府県名一覧やカテゴリーなど「基本的に変更されないデータ」を扱うときに便利です。  

ここでは例として商品の送り元住所の都道府県登録にActiveHashを用います。

## ActiveHashの導入
Gemfileの最下部に
```ruby
gem 'active_hash'
```
を追記し、`bundle install`を実行します。

## モデルの作成
Itemモデルを作成します。

次に、都道府県名を管理するPrefectureモデル(厳密にはActiveHashを用いたクラス)を作成します。

データベースを利用しないため、手動で
app/modelsディレクトリ内にprefecture.rbを作成します。

まずは、モデルの「Prefectureクラス」を定義し、ActiveHash::Baseクラスを継承します。
次に、都道府県名のデータは、配列にハッシュ形式で格納します。

**app/models/prefecture.rb**
```ruby
class Prefecture < ActiveHash::Base
  self.data = [
    { id: 1, name: '---' }, { id: 2, name: '北海道' }, { id: 3, name: '青森県' },
    { id: 4, name: '岩手県' }, { id: 5, name: '宮城県' }, { id: 6, name: '秋田県' },
    { id: 7, name: '山形県' }, { id: 8, name: '福島県' }, { id: 9, name: '茨城県' },
    { id: 10, name: '栃木県' }, { id: 11, name: '群馬県' }, { id: 12, name: '埼玉県' },
    { id: 13, name: '千葉県' }, { id: 14, name: '東京都' }, { id: 15, name: '神奈川県' },
    { id: 16, name: '新潟県' }, { id: 17, name: '富山県' }, { id: 18, name: '石川県' },
    { id: 19, name: '福井県' }, { id: 20, name: '山梨県' }, { id: 21, name: '長野県' },
    { id: 22, name: '岐阜県' }, { id: 23, name: '静岡県' }, { id: 24, name: '愛知県' },
    { id: 25, name: '三重県' }, { id: 26, name: '滋賀県' }, { id: 27, name: '京都府' },
    { id: 28, name: '大阪府' }, { id: 29, name: '兵庫県' }, { id: 30, name: '奈良県' },
    { id: 31, name: '和歌山県' }, { id: 32, name: '鳥取県' }, { id: 33, name: '島根県' },
    { id: 34, name: '岡山県' }, { id: 35, name: '広島県' }, { id: 36, name: '山口県' },
    { id: 37, name: '徳島県' }, { id: 38, name: '香川県' }, { id: 39, name: '愛媛県' },
    { id: 40, name: '高知県' }, { id: 41, name: '福岡県' }, { id: 42, name: '佐賀県' },
    { id: 43, name: '長崎県' }, { id: 44, name: '熊本県' }, { id: 45, name: '大分県' },
    { id: 46, name: '宮崎県' }, { id: 47, name: '鹿児島県' }, { id: 48, name: '沖縄県' }
  ]
end
```

## マイグレーションファイルを編集
itemsテーブルのカラムに`prefecture_id`を追加します。  
**ターミナル**
```
% rails db:migrate
```
を実行します。

## アソシエーションを設定
### Itemモデルのアソシエーションを設定
Itemモデルにはbelongs_toを設定します。

ActiveHashを用いて、`belongs_to`を設定するには、  
`extend ActiveHash::Associations::ActiveRecordExtensions`と記述してmoduleを取り込みます。
 
**app/models/item.rb**
```ruby
class Article < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :prefecture
end
```

### Prefectureモデルのアソシエーションを設定
Prefectureモデルには`has_many`を設定します。

ActiveHashを用いて、`has_many`を設定するには、
`include ActiveHash::Associations`と記述してmoduleを取り込みます。

prefecture.rbに以下を追記しましょう。

**app/models/prefecture.rb**
```ruby
class Prefecture < ActiveHash::Base
  self.data = [
    # 省略
  ]

  include ActiveHash::Associations
  has_many :items
end
```

## バリデーションを設定
**app/models/item.rb**
```ruby
class Article < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :prefecture

  validates :prefecture_id, numericality: { other_than: 1 } 
```
`numericality`で、数値かどうかを検証しています。
また`other_than: 1`で`id: 1`以外であれば保存できるように設定しています。
今回は「---」のidが1なので、このように記述しています。


## 登録フォームにプルダウン形式で表示
フォーム内に以下の記述を追加します。(他の部分は省略しています）
**app/views/item/new.html.erb**
```ruby
<%= f.collection_select(:prefecture_id, Prefecture.all, :id, :name, {}) %>
```
**collection_select**を用いることで、データをプルダウン形式で表示しています。
引数は以下のように指定します。
```ruby
<%= form.collection_select(保存するカラム名, オブジェクトの配列, カラムに保存する項目, 選択肢に表示されるカラム名, オプション, htmlオプション) %>
```
今回はオプションを指定しないため`{}`としています。