Settingslogicの置き換えを狙ったSettingsCabinetを発明した
事の起こり
車輪の再発明をしました。
Railsのプロジェクトで設定の管理によく使われている気がするgemにSettingslogicがあります。
大変よくできており、RubyGemsに公開されている最新バージョンである2.0.9[1]が2012年12月公開[2]であるにも関わらずRuby(MRI) 3.0でも動作していました。
動作していました。
そう、3.0までは。
Ruby 3.1でYAMLのバックエンドであるPsychが4.0に変更になったことにより壊れました。
詳細はここでは割愛しますが、以下のようにサポートするためのPRが出てはいますが取り込まれるかどうかは怪しいものです。
どうしよう
動かないものは仕方がないので対応法を検討しました。
これらと同様のパッチを当てて使うというのもアリ[3]ですが、開発が続いていないものを使い続けるよりも他のものに移行するのが良いと考えました。
移行先の候補としては以下の2つです
- Railsの標準の
config_for
を使う - config gemを使う
https://github.com/rubyconfig/config
1は単なるHashになってしまうというのが好みではないです
2はdry-*系のgemに依存しているために依存関係が多い[4]のが好みではないし設定ファイルを1つにまとめることを強いられそう[5]なのも好みではないです
やることは一つしかない
移行先の候補がイマイチなら再発明しかないということで車輪の再発明をしました。
SettingsCabinetと名付けました。
仮でPrettySettingsという名前で開発していましたがいけてない気がして変えました。
特段すごい機能はないのですが概ね以下のような感じになっています。
- Settingslogic風の使い勝手
- ERBが使えるYAMLの設定ファイル
- DSLはほぼ同じ
- Dynamic settings[6]はサポートしない
- 複数種類の設定ファイルのサポート
- 設定ファイルの読み込みがスレッドセーフ(多分できているはず)
- メソッドによるアクセスとHash風のアクセスが可能
- 現状では他gemへの依存なし
- Refinementsを活用した実装[7]
defaults: &defaults
foo: 1
bar: <%= 2 * 2 %>
date: 2022-04-24
time: 2024-04-24T12:34:56+09:00
symbol: :symbol
nested:
child: "child"
development:
<<: *defaults
foo: 2
test:
<<: *defaults
foo: 3
production:
<<: *defaults
foo: 4
class Settings < SettingsCabinet::Base
using SettingsCabinet::DSL
source Rails.root.join("config/settings.yml")
namespace Rails.env
permitted_classes [Date, Time, Symbol]
end
# RAILS_ENV=development
Settings.foo #=> 2
Settings.nested.child #=> "child"
そういうわけで置き換えた
SettingslogicからSettingsCabinetに置き換えて無事に動きました。[8]
終わりに
良かったら使ってみていただけると嬉しいです。
そのうちいつかKMSサポートなどをやりたい気がしています。やる気だけはあります。
-
GitHubの最終更新は2014年8月 https://github.com/settingslogic/settingslogic/commit/463073f8c42fa9b5d976ccd5b8c98f433a18f42e ↩︎
-
Settingslogicはコードベースが小さいため今後他の問題が出ても対処可能であろうと考えています ↩︎
-
検証系の機能を使うならまあいいのだろうが使う予定はないし依存関係は少ない方が良いですよね ↩︎
-
設定の種類に応じて分けたいときもありますよね ↩︎
-
https://github.com/settingslogic/settingslogic/tree/463073f8c42fa9b5d976ccd5b8c98f433a18f42e#4-optional--dynamic-settings- ↩︎
-
ライブラリーの都合で設定ファイルのキーに使える名前を減らしたくなかった ↩︎
-
とは言うもののこれを書いている時点ではまだプロダクションにリリースはしていません ↩︎
Discussion