はじめに
Railsアプリケーションの実装で新たにマスタデータを持つ必要が出てきた時に「わざわざテーブルを作りたくない」と思ったことはないでしょうか。
「他テーブルと結合して使うわけでもない」「基本的に更新されない(ほぼ固定値のようなもの)」「データ数も多くない」といった条件が重なってくると、マスタ管理のためだけにテーブルを増やすのは少し抵抗があります。
そんな時に役立ちそうな方法をまとめてみました。
方法1, ActiveModel & クラス内に直接定義
ActiveModel
を読み込み、マスタデータもクラス内で全て定義してしまう方法です。ごく一部の機能さえあれば良く、とにかくシンプルに済ませたい時に向いています。
class Region
include ActiveModel::Model
attr_accessor :code, :name
DATA = [
{ code: "R01", name: "北海道地方" },
{ code: "R02", name: "東北地方" },
{ code: "R03", name: "関東地方" },
{ code: "R04", name: "中部地方" },
{ code: "R05", name: "近畿地方" },
{ code: "R06", name: "中国地方" },
{ code: "R07", name: "四国地方" },
{ code: "R08", name: "九州・沖縄地方" }
].freeze
# 区域一覧を取得
def self.all
DATA.map { |item| self.new(item) }
end
end
self.all
で定義した通り、区域一覧を取得することができています。
Region.all
=>
[#<Region:0x0000ffff81da9a40 @code="R01", @name="北海道地方">,
#<Region:0x0000ffff81da9720 @code="R02", @name="東北地方">,
#<Region:0x0000ffff81da96a8 @code="R03", @name="関東地方">,
#<Region:0x0000ffff81da9630 @code="R04", @name="中部地方">,
#<Region:0x0000ffff81da95b8 @code="R05", @name="近畿地方">,
#<Region:0x0000ffff81da9540 @code="R06", @name="中国地方">,
#<Region:0x0000ffff81da94c8 @code="R07", @name="四国地方">,
#<Region:0x0000ffff81da9428 @code="R08", @name="九州・沖縄地方">]
Pros
-
gem
も不要かつ1ファイルのみで完結するためとにかくシンプル
Cons
- マスタデータの量や項目が多いとコードの見通しが悪くなる
- 必要な処理は自分で書く必要がある
方法2, ActiveModel & YAMLファイル
ActiveModel
を使いつつマスタデータをYamlファイルから読み込むように変更したものです。「クラス内でマスタデータを定義するには量や項目が多い」といった場合はこちらの方が良いでしょう。
class Region
include ActiveModel::Model
attr_accessor :code, :name
# yamlからデータをロード
def self.data
@data ||= YAML.load_file(Rails.root.join('config', 'master_data', 'regions.yml'))
end
# 区域一覧を取得
def self.all
data.map { |item| self.new(item) }
end
end
- code: R01
name: 北海道地方
- code: R02
name: 東北地方
- code: R03
name: 関東地方
- code: R04
name: 中部地方
- code: R05
name: 近畿地方
- code: R06
name: 中国地方
- code: R07
name: 四国地方
- code: R08
name: 九州・沖縄地方
Pros
- データとコードが分離されているため管理しやすい
- データが増えてもコードの可読性を損なわない
Cons
- 必要な処理についてはやはり自分で書く必要がある
方法3, ActiveHash & クラス内に直接定義
gem active_hash
を利用する方法です。gemをインストールする必要はありますが、1ファイルで完結する上に ActiveRecord
と同じ感覚で使うことができます。
導入も簡単。まずはgemをインストールします。
gem 'active_hash'
そして、ActiveHash::Base
を継承してクラスを作成します。self.data
でマスターデータを定義してください。
class Region < ActiveHash::Base
self.data = [
{ code: "R01", name: "北海道地方" },
{ code: "R02", name: "東北地方" },
{ code: "R03", name: "関東地方" },
{ code: "R04", name: "中部地方" },
{ code: "R05", name: "近畿地方" },
{ code: "R06", name: "中国地方" },
{ code: "R07", name: "四国地方" },
{ code: "R08", name: "九州・沖縄地方" }
]
end
all
、 find_by
等、ActiveRecord
でよく使う処理と同様のことができます。
Region.all
=>
[#<Region:0x0000ffff80b895e0 @attributes={:code=>"R01", :name=>"北海道地方", :id=>1}>,
#<Region:0x0000ffff80b88bb8 @attributes={:code=>"R02", :name=>"東北地方", :id=>2}>,
#<Region:0x0000ffff80b88730 @attributes={:code=>"R03", :name=>"関東地方", :id=>3}>,
#<Region:0x0000ffff80b88348 @attributes={:code=>"R04", :name=>"中部地方", :id=>4}>,
#<Region:0x0000ffff80b87f60 @attributes={:code=>"R05", :name=>"近畿地方", :id=>5}>,
#<Region:0x0000ffff80b87b78 @attributes={:code=>"R06", :name=>"中国地方", :id=>6}>,
#<Region:0x0000ffff80b87790 @attributes={:code=>"R07", :name=>"四国地方", :id=>7}>,
#<Region:0x0000ffff80b873a8 @attributes={:code=>"R08", :name=>"九州・沖縄地方", :id=>8}>]
Region.find_by(code: "R03")
=> #<Region:0x0000ffffa1e48828 @attributes={:code=>"R03", :name=>"関東地方", :id=>3}>
Pros
-
ActiveRecord
と同様の感覚で利用することができる - 1ファイルで完結するためシンプル
Cons
- gemへの依存は生まれる
- マスタデータの量や項目が多いとコードの見通しが悪くなる
方法4, ActiveHash & YAMLファイル
gem active_hash
をインストールすると、YAMLファイルをロードして ActiveHash
オブジェクトとして扱えるようにする ActiveYaml
クラスを使えるようになります。
ActiveYaml::Base
を継承してクラスを作成し、set_root_path
でマスタデータのYAMLファイルを設置しているディレクトリを、set_filename
で読み込むYAMLファイルを指定してください。
class Region < ActiveYaml::Base
set_root_path Rails.root.join("config", "master_data")
set_filename "regions"
end
方法3と同様に、ActiveRecord
と同じ感覚で操作ができます。
Region.find_by(code: "R02")
=> #<Region:0x0000ffff803b1ea8 @attributes={:code=>"R02", :name=>"東北地方", :id=>2}>
Pros
-
ActiveRecord
と同様の感覚で利用することができる - データとコードが分離されているため管理しやすい
- データが増えてもコードの可読性を損なわない
Cons
- gemへの依存は生まれる
まとめ
マスタデータの量や項目、必要としている機能や実装の手間に応じて適した方法を選択するのが良いでしょう。コードの可読性という観点から、データについてはYAMLファイルで管理した方が感覚的にスッキリはしました。
4つ全てを試した感じでは 「方法4, ActiveHash & YAMLファイル」 がコードの見通しもよく実装の手間も省けて良かったのですが、「どうしてもgemへの依存を避けたい」というような場合は ActiveModel
を使って自分で実装するという選択肢も生まれてくるかと思います。
参考
GitHub - active-hash/active_hash
【Rails】ActiveHashでマスターデータを管理する