ActiveHash の使い方 まとめ
Active_Hashとは、、、
都道府県名などの変更されないデータを「モデルファイル内」に直接記述することで、
データベースへ保存せずにデータを取り扱うことができる Gem のこと。
ActiveHash導入方法
Gemfileを編集
gem 'active_hash'
記述したらbundle installを実行
例 ArticleモデルでActiveHashを導入
記事を管理するArticleモデル
記事のジャンルを管理するGenreモデル
記事のジャンルは変更されないデータ=ActiveHashを用いて管理
①それぞれのモデルを作成
rails g model article
rails g model genre --skip-migration
--skip-migrationとは??
モデルファイルを作成するときに、マイグレーションファイルの生成を行わないためのオプション。今回、記事のジャンルの情報はデータベースに保存しない=マイグレーションファイルを作成する必要はない。
②genreモデルでクラスを定義し、ActiveHash::Base を継承するための記述を行う
ジャンルのデータは、配列にハッシュ形式で格納
class Genre < ActiveHash::Base
self.data = [
{ id: 1, name: '--' },
{ id: 2, name: '経済' },
{ id: 3, name: '政治' },
{ id: 4, name: '地域' },
{ id: 5, name: '国際' },
{ id: 6, name: 'IT' },
{ id: 7, name: 'エンタメ' },
{ id: 8, name: 'スポーツ' },
{ id: 9, name: 'グルメ' },
{ id: 10, name: 'その他' }
]
end
③①で生成されたarticleのマイグレーションファイルを編集・マイグレートする
以下の様に編集し ⇨ rails db:migrate
Articlesテーブルの中にgenre_idという名前のカラムを作成しているのは、投稿した記事を表示する際に、その記事に紐付いたジャンルを取得するため
Articleテーブルの中で、Genreモデル(ActiveHash)のidを外部キーとして管理することで、その記事に紐付いたジャンルの取得が実現
class CreateArticles < ActiveRecord::Migration[6.0]
def change
create_table :articles do |t|
t.string :title , null: false
t.text :text , null: false
t.integer :genre_id , null: false
t.timestamps
end
end
end
④モデル間でのアソシエーションの設定
ActiveHashを用いてアソシエーションを設定する場合は、ActiveHashで定義されているmoduleをモデルに取り込む必要がある。
1)ActiveHashを導入したい(される)モデル
投稿する記事=Articleは、1つのジャンル=Genreに紐付いています。そのため、Articleモデルにbelongs_toを設定します。
ActiveHashを用いて、belongs_toを設定するには、
extend ActiveHash::Associations::ActiveRecordExtensionsと記述してmoduleを取り込みます。
class Article < ApplicationRecord
extend ActiveHash::Associations::ActiveRecordExtensions
belongs_to :genre
end
2)ActiveHashを設定したモデル
1つのジャンル=Genreは、たくさんの投稿物=Articlesに紐付いています。そのため、Genreモデルにはhas_manyを設定します。
ActiveHashを用いて、has_manyを設定するには、
include ActiveHash::Associationsと記述してmoduleを取り込みます。
class Genre < ActiveHash::Base
self.data = [
{ id: 1, name: '--' },
〜〜〜省略〜〜〜
{ id: 10, name: 'その他' }
]
include ActiveHash::Associations
has_many :articles
end
※moduleとは、特定の役割を持つメソッドや定数に名前を付けてまとめたもの。どのようなmoduleが定義されているかは、こちらのリファレンスで確認。
※ActiveHashを用いたアソシエーションの設定は、他にもあります。詳しくはこちらのドキュメントを確認。
⑤バリデーションを設定
データベースに空の投稿が保存されないようにする場合、バリデーションヘルパーのnumericality(数値かどうかを検証する)を用いる。数値であればデータベースに保存を許可して、それ以外では保存が許可されないようにできます。今回においては、--を保存されないようにしたいので、id: 1以外であれば保存できるように設定すると
class Article < ApplicationRecord
extend ActiveHash::Associations::ActiveRecordExtensions
belongs_to :genre
#空の投稿を保存できないようにする
validates :title, :text, presence: true
#ジャンルの選択が「--」の時は保存できないようにする
validates :genre_id, numericality: { other_than: 1 }
end
このバリデーションは、genre_idのid:1以外のときに保存できるという意味になる。
導入については以上です。ジャンル選択のプルダウン生成などはview関連になるため
別記事に追記予定。