💎

Settingslogicの置き換えを狙ったSettingsCabinetを発明した

2022/04/24に公開

事の起こり

車輪の再発明をしました。

Railsのプロジェクトで設定の管理によく使われている気がするgemにSettingslogicがあります。
https://github.com/settingslogic/settingslogic

大変よくできており、RubyGemsに公開されている最新バージョンである2.0.9[1]が2012年12月公開[2]であるにも関わらずRuby(MRI) 3.0でも動作していました。

動作していました。
そう、3.0までは。

Ruby 3.1でYAMLのバックエンドであるPsychが4.0に変更になったことにより壊れました。
詳細はここでは割愛しますが、以下のようにサポートするためのPRが出てはいますが取り込まれるかどうかは怪しいものです。
https://github.com/settingslogic/settingslogic/pull/21
https://github.com/settingslogic/settingslogic/pull/22

どうしよう

動かないものは仕方がないので対応法を検討しました。
これらと同様のパッチを当てて使うというのもアリ[3]ですが、開発が続いていないものを使い続けるよりも他のものに移行するのが良いと考えました。

移行先の候補としては以下の2つです

  1. Railsの標準の config_for を使う
  2. config gemを使う
    https://github.com/rubyconfig/config

1は単なるHashになってしまうというのが好みではないです
2はdry-*系のgemに依存しているために依存関係が多い[4]のが好みではないし設定ファイルを1つにまとめることを強いられそう[5]なのも好みではないです

やることは一つしかない

移行先の候補がイマイチなら再発明しかないということで車輪の再発明をしました。

SettingsCabinetと名付けました。
仮でPrettySettingsという名前で開発していましたがいけてない気がして変えました。

https://github.com/yujideveloper/settings_cabinet
https://rubygems.org/gems/settings_cabinet

特段すごい機能はないのですが概ね以下のような感じになっています。

  1. Settingslogic風の使い勝手
    • ERBが使えるYAMLの設定ファイル
    • DSLはほぼ同じ
    • Dynamic settings[6]はサポートしない
  2. 複数種類の設定ファイルのサポート
  3. 設定ファイルの読み込みがスレッドセーフ(多分できているはず)
  4. メソッドによるアクセスとHash風のアクセスが可能
  5. 現状では他gemへの依存なし
  6. Refinementsを活用した実装[7]
config/settings.yml
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
config/settings.rb
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サポートなどをやりたい気がしています。やる気だけはあります。

脚注
  1. https://rubygems.org/gems/settingslogic/versions/2.0.9 ↩︎

  2. GitHubの最終更新は2014年8月 https://github.com/settingslogic/settingslogic/commit/463073f8c42fa9b5d976ccd5b8c98f433a18f42e ↩︎

  3. Settingslogicはコードベースが小さいため今後他の問題が出ても対処可能であろうと考えています ↩︎

  4. 検証系の機能を使うならまあいいのだろうが使う予定はないし依存関係は少ない方が良いですよね ↩︎

  5. 設定の種類に応じて分けたいときもありますよね ↩︎

  6. https://github.com/settingslogic/settingslogic/tree/463073f8c42fa9b5d976ccd5b8c98f433a18f42e#4-optional--dynamic-settings- ↩︎

  7. ライブラリーの都合で設定ファイルのキーに使える名前を減らしたくなかった ↩︎

  8. とは言うもののこれを書いている時点ではまだプロダクションにリリースはしていません ↩︎

Discussion