この記事は
- RailsでDBにサイト設定情報を持たせて画面から設定させたかったです
- ここでいうサイト設定というのは、例えばサイトのタイトルみたいな、あとからちょくちょく変えたくなるようなアプリケーションレイヤの設定項目です
- 設定ファイルに記述する方式でよければrails configとか使えばいいのですが、スピードと分業の都合でリアルタイムに画面から変更したかったです
対応方針
rails-settings-cached gem
- rails-settings-cachedというgemを使ってやってみました
- このgem、元々はrails-settingsのforkらしいのですが、跡形もないくらいにいじられているので、完全に別物と思ってください
このgemのいいところ
DB構成が手軽
- まずDBにデータを保存するという基本的な構成が想定通りです
- かつ、保持させたい設定情報がキーバリュー方式の2つのカラムで管理されていて手軽です
- 対する方式としては、設定項目ごとにカラムを追加するというやりかたもありますが、これだと、設定項目が増える度につどつどmigrationが入ってめんどくさいです
性能について考えられている
- それから、性能を改善するために、RequestStoreにデータを入れて再利用しています
- Railsのリクエスト開始時に最新の設定情報を取りに行って、同一リクエスト内では同じものを使い回す
- リクエスト終了時に設定情報を破棄する
- RequestStoreを利用しているおかげで、呼び出すたびにDBアクセスはしないですんでおり、ある程度SQL発行回数を抑制しつつ、複数APサーバでも動的な設定情報変更が反映できる構成になっています
- 多分gem名のcachedというのはここの部分を指していると思います。
導入手順
gemのインストール
- gemを普通に入れます
Gemfile
gem "rails-settings-cached", "~> 2.0"
DBテーブルの追加
rakeが・・・
- テーブル追加したりモデルクラスを追加するrakeが付いているのですが、なぜかエラーが出て使えませんでした
- なので、ソースのtemplateを参考に下記のようなクラスを作りました
-
sample_configs
/SampleConfig
というなまえのテーブル/モデルを作るものとします
-
テーブル定義
- 今みてるRailsアプリケーションがRidgepoleを使っているので、下記のように定義しました。
- rails標準のmigrationでも同じような事を書けば大丈夫だと思います
Schemafile
create_table :sample_configs, id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" do |t|
t.string :var, null: false
t.text :value, null: true
t.timestamps
t.index :var, name: 'index_sample_configs_var', unique: true
end
モデル定義
- こんな感じに定義します
- ポイントはfieldに定義するときにハードコードでデフォルト値を設定できるというところです
- DBに値がなかった場合は自動的にこちらを参照してくれるので、運用によっては結構便利だと思います。
app/models/sample_config.rb
# RailsSettings Model
class SampleConfig < RailsSettings::Base
self.table_name = 'sample_configs'
cache_prefix { "v1" }
# Define your fields
# field :host, type: :string, default: "http://localhost:3000"
# field :default_locale, default: "en", type: :string
# field :confirmable_enable, default: "0", type: :boolean
# field :admin_emails, default: "admin@rubyonrails.org", type: :array
# field :omniauth_google_client_id, default: (ENV["OMNIAUTH_GOOGLE_CLIENT_ID"] || ""), type: :string, readonly: true
# field :omniauth_google_client_secret, default: (ENV["OMNIAUTH_GOOGLE_CLIENT_SECRET"] || ""), type: :string, readonly: true
field :example1, type: :text, default: "hello!"
end
使い方
- こんな感じで普通に使えます
- field定義するときに指定した型に応じて適当にキャストされて返ってくるのもなかなか便利です
some_controler.rb
def some_action
render text: SampleConfig.example1
end
- ちなみに値を代入するだけでsaveせずともDBが更新されてしまうのでそこだけは注意してください
- モンキーパッチで潰しておいた方がいいかも
ActiveAdminの利用
- わざわざDBに値を保持させたので、画面から更新したくなると思います
- まあまあよく使われているActiveAdminを利用して、普通にこれらの値を画面から更新することができます
- 下記ファイルを作成すれば、普通に画面からCRUDでメンテできるようになります
app/admin/sample_configs.rb
ActiveAdmin.register SampleConfig do
permit_params :var, :value
end
終わりに
- 全然有名じゃないgemな気がしますが、結構いい感じだなとおもいました