【Ruby on Rails】 gem を使わないで環境毎に定数管理をする

概要

Rails で定数管理するにはたくさんの gem が存在しています。

定数管理の gem で有名なものだとここら辺の名前が上がるかと思います。

config は環境毎に Yaml ファイルを用意して定数を管理するので、大規模アプリケーション向けのイメージがあります。管理する定数が多い場合にオススメです。

settingslogic は 1 つの Yaml ファイルで環境毎の定数を管理するので、中小規模アプリケーション向けのイメージがあります。管理する定数が少ないのであれば見やすくてオススメです。

 

ただ、ここで....

『定数管理ぐらい自分で実装できないの?』と疑問に思ったことがあります。

そこで、自分が実装した定数管理方法についてまとめました。

はじめに

gem を使わない定数管理方法だと、最初にこの 2 つの方法が思いつきます。

  • application_controller.rb で定数を管理する方法
  • app/initializers/constants.rb のようなファイルを用意して、そこで定数を管理する方法

application_controller.rb はアプリケーション共通の処理を管理する場所なので、定数を管理するには相応しくないと思いました。

app/initializers/constants.rb のようなファイルを用意して、そこで定数を管理する方法は賛成です。

ただし、環境毎の定数管理を見やすくするため、Ruby ファイルではなく、Yaml ファイルを利用します。

Yaml ファイルを利用した定数管理用法

用意するファイルは 2 つです。

  • config/constants.yml
  • config/initializers/00_load_config.rb

config/constants.yml

これは定数を管理するためのファイルです。

Yaml のアンカーとエイリアスを利用して、環境毎の出し分けを行います。

# アプリケーション共通の設定を記載します
common: &common
domain:
example: http://example.com/
port:
- 80
- 443
message: This is application common setting
# 開発環境の設定を記載します development: <<: *common
message: This is development environment setting
# 本番環境の設定を記載します production: <<: *common
message: This is production environment setting

config/initializers/00_load_config.rb

これは定数管理用ファイルを読み込むためのファイルです。

file = "#{Rails.root}/config/constants.yml"

# 再帰的にオブジェクトを凍結します
def deep_freeze(hash)
hash.freeze.each_value do |i|
i.kind_of?(Hash) ? deep_freeze(i) : i.freeze
end
end

CONFIG = deep_freeze(YAML.load_file(file)[Rails.env].deep_symbolize_keys)

 

deep_symbolize_keys は再帰的にシンボル形式に変換してくれます。

https://apidock.com/rails/v4.0.2/Hash/deep_symbolize_keys

freeze は オブジェクトを凍結、つまり変更不可 (定数) にします。

http://ref.xaio.jp/ruby/classes/object/freeze

定数取得

定数の取得を試してみます。

$ rails c
Loading development environment (Rails 5.0.2)
irb(main):001:0> CONFIG
=> {:domain=>{:example=>"http://example.com/", :port=>[80, 443]}, :message=>"This is development environment setting"}

# 開発環境用の設定に上書きされています
irb(main):002:0> CONFIG[:message]
=> "This is development environment setting"

# 凍結されています
irb(main):003:0> CONFIG.frozen?
=> true

# ネストした値も凍結されています
irb(main):004:0> CONFIG[:domain][:exapmle].frozen?
=> true

# 変更しようとするとエラーになります
irb(main):005:0> CONFIG[:message] << 'Hello'
RuntimeError: can't modify frozen String

まとめ

定数管理を自分で実装することは簡単にできました。

自分で実装することの利点はこの 2つかなと思います。

  • 仕様を把握できる点
  • 自分で拡張できる点

ただし、1 つの Yaml ファイルで全ての定数を管理するので、中小規模アプリケーション向けの方法だと思います。

最後に

Rails の定数管理方法に答えはないと思います。

どの方法も一長一短なので、開発しているアプリケーションに合った方法を見極めて採用するのがいいと思います。