はじめに
Railsの設定定数をYAMLファイルで管理するのにEasySettingsというGemを使う方法です。
使い方
Gemfile
に
gem "easy_settings"
を追加して、config/settings.yml
に次のようなYAMLファイルを作ります。
default: &default
key1: value1
development:
<<: *default
key2: value2.d
test:
<<: *default
key2: value2.t
production:
<<: *default
key2: value2.p
あとはアプリのどこからでも次のようにして値を参照できます。
EasySettings.key2 #=> "value2.d"
他の定数管理
他にもいろいろあります。
Settingslogic
Settingslogicはこの中でも最もシンプルで1つのYAMLで定数を管理します。
機能といえばERBが処理できることとファイル内で名前空間が設定できることぐらいです。
Settingslogic
クラスを継承したクラスを定義する必要があります。
EasySettingsは元々Settingslogicの代替として作られたためSettingslogicに似ています。
Config
元々はrails_configというGemだったようです。
複数のYAMLファイルに継承関係を持たせて定数を定義できます。
Chamber
Chamber is the auto-encrypting, extremely organizable, Heroku-loving, CLI-having, non-extra-repo-needing, non-Rails-specific-ing, CI-serving configuration management library.
だそうです。ドキュメントも多くてやりたいことに対して大げさすぎる気がするのであんまり調べてません。
特徴
といっても機能はそんなにありません。EasySettingsはただのYAMLを読み込むHashie::Mashです。
Settingslogicの不満点を解消するために作ったのでSettingslogicと比較しながら説明します。
メソッド形式、ハッシュ形式(String、Symbol)で参照できる
これはSettingslogicでもできますね。
例えば設定ファイルがこんな感じだと、
development:
key1:
subkey1: value1
subkey2: value2
こんな感じで参照できます。
>> EasySettings.key1
=> #<EasySettings subkey1="value1" subkey2="value2">
>> EasySettings[:key1]
=> #<EasySettings subkey1="value1" subkey2="value2">
>> EasySettings["key1"]
=> #<EasySettings subkey1="value1" subkey2="value2">
>> EasySettings.key1.to_h
=> {"subkey1"=>"value1", "subkey2"=>"value2"}
>> EasySettings.key1.subkey1
=> "value1"
>> EasySettings.key1[:subkey1]
=> "value1"
>> EasySettings.key1["subkey1"]
=> "value1"
ハッシュはEasySettings
のオブジェクトになりますがto_h
でHash
オブジェクトに変換できます。
初期化いらず
Settingslogicはどこかで次のようにクラスを定義する必要があります。
class Settings < Settingslogic
source Rails.root.join("config/settings.yml").to_s
namespace Rails.env
end
EasySettingsは不要です。あえていうならGemfile
に1行必要なぐらい。
未定義のメソッド形式で例外が発生しない
Settingslogicでは定義されていないキーをメソッド形式で参照しようとすると例外が発生します。
# Settingslogicは例外発生
>> Settings.undefined_key
Settingslogic::MissingSetting: Missing setting 'undefined_key' in /tmp/app/config/settings.yml
# EasySettingsはnilになる
>> EasySettings.undefined_key
=> nil
EasySettingsの場合メソッド形式で代入もできます。
# Settingslogicだとエラー
>> Settings.existed_key = "new value"
Settingslogic::MissingSetting: Missing setting 'existed_key=' in /tmp/app/config/settings.yml
# EasySettingsはOK
>> EasySettings.existed_key = "new value"
=> "hoge"
デフォルト値が設定できる
デフォルト値が設定できます。機能的には一番強力かもしれません。
例えばこういうときに、
class User < ActiveRecord::Base
paginates_per(Settings[:per_page] || 5)
end
EasySettingsではこのように書けます。
class User < ActiveRecord::Base
paginates_per EasySettings.per_page(5)
end
さらに、EasySettingsでは末尾に!
をつけるとキーが定義されていない場合だけハッシュとして初期化します。
>> EasySettings.new_key
=> nil
>> EasySettings.has_key?(:new_key)
=> false
>> EasySettings.new_key!
=> #<EasySettings>
>> EasySettings.has_key.to_h
=> {}
>> EasySettings.has_key?(:new_key)
=> true
EasySettings.new_key({})
とEasySettings.new_key!
は同じ意味です。
これは設定に入れ子ハッシュがある場合に威力を発揮します。
例えばpaginates_per
をYAMLでは次のように書きたい時、
development:
pagination:
per_page: 5
これを次のように書いてしまうと、pagination
がnilの場合エラーになります。
pagenates_per(Settings[:pagination][:per_page] || 5)
なので、最低でもYAMLファイルに空ハッシュを書くようにするか、
development:
pagination: {}
アプリ側をこのようにする必要があります。
paginates_per((Settings[:pagination] || {})[:per_page] || 5)
やってられませんね。EasySettingsならこうです。
pagenates_per EasySettings.pagination!.per_page(5)
別名が使える
EasySettings
という名前は長いです。短くしたいという時はこうします。
Config = EasySettings
config/initializers/easy_settings.rb
とかに書いておけばいいと思います。
config/settings.yml以外
config/settings.yml
以外を使いたい場合、EasySettings.source_file=
メソッドで設定ファイルを指定します。
ついでに紹介しておくと、EasySettings.namespace=
とかEasySettings.reload!
とかいうのもあります。
config/initializers/easy_settings.rb
に次のように書くと環境ごとにYAMLファイルを切り替えられます。
EasySettings.source_file = Rails.root.join("config/settings/#{Rails.env}.yml")
EasySettings.namespace = nil
EasySettings.reload!
Config = EasySettings
ERBが使える
ERBを処理できます。
default: &default
aws_id: <%= ENV["AWS_ID"] %>
aws_secret: <%= ENV["AWS_SECRET"] %>
みたいな感じです。dotenvと組み合わせられます。
Rails以外でも使える
元々はRails以外で使うために作りました。
Rails以外で使うとき、Dir.pwd
からみてsettings.yml
かconfig/settings.yml
にファイルが存在すればそれを読むようになっています。
それ以外に設定ファイルがあるときはEasySettings.source_file=
を使って下さい。
その他Settingslogicのおかしな挙動
ついでなので、他にもレアケースですがSettingslogicにおかしな挙動があってハマりました。
例えばデフォルト値を設定してその後も使い回す例です。
>> (Settings[:pagination] ||= {})[:per_page] ||= 5
=> 5
>> Settings[:pagination][:per_page]
=> nil
あと入れ子になるハッシュで同じキーを突っ込んだ場合。
>> Settings[:foo] = {foo: "bar"}
=> {:foo=>"bar"}
>> Settings.foo
=> {:foo=>"bar"}
>> Settings.foo.foo
Settingslogic::MissingSetting: Missing setting 'foo' in /tmp/app/config/settings.yml
おわりに
最後はSettingslogicディスみたいになってしまいましたが、基本はSettingslogicのシンプルなところをリスペクトして作ったGemです。
設定管理のお供にいかがでしょうか