41
38

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Railsの設定定数をYAMLで一元管理する(EasySettings)

Last updated at Posted at 2015-10-05

はじめに

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_hHashオブジェクトに変換できます。

初期化いらず

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ファイルを切り替えられます。

config/initializers/easy_settings.rb
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.ymlconfig/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です。
設定管理のお供にいかがでしょうか:smile::sparkles:

41
38
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
38

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?