デプロイ中にセッションを飛ばさないために、 セッションをアプリケーション外に保存するケースがあります。 今回はそういったケースのために、 RailsのセッションをRedisに保存できる redis-store/redis-rails を使ってみました。

まずは素のRailsプロジェクトを作成

まずは素のRailsプロジェクトを作成します。 最初のウェルカムページだけだとセッションが生成されないので、 今回はTodo管理システムを作るということにして、 Scaffoldを使っていきます。 ちなみにRailsのバージョンは5.1.4を使っていきます。

$ rails new redis-rails-sample --skip-bundle --skip-turbolinks
$ cd redis-rails-sample
$ bundle install --path vendor/bundle
$ rails g scaffold Task title:string status:integer

redis-railsをインストール

次にredis-store/redis-railsを インストールして設定を書いていきます。 Gemfileにgem 'redis-rails'と書いて、bundle installを実行します。

次にconfig/application.rbを以下のように編集します。

module RedisRailsSample
  class Application < Rails::Application
    # ...

    # これを追記
    config.cache_store = :redis_store, "redis://localhost:6379/0/cache", { expires_in: 90.minutes }
  end
end

最後にconfig/initializers/session_store.rbというファイルを作成し、 以下の内容にします。

RedisRailsSample::Application.config.session_store :redis_store, {
  servers: [
    {
      host: "localhost",
      port: 6379,
      db: 0,
      namespace: "session"
    },
  ],
  key: "_#{Rails.application.class.parent_name.downcase}_session"
}

Redisにセッションが保存されるか確認

ローカルでRedisとRailsを立ち上げて、ブラウザで http://localhost:3000/tasksにアクセスしてみましょう。

ちなみにここで(error) DENIED Redis is running in protected mode because protected mode is enabled ~ というエラーが発生する場合は、下記を参考にしてください。

redis で because protected mode is enabled が出た場合の対処 - Qiita

redis-cliを使ってRedisの中身を確認すると、セッションが保存されているのが確認できます。

$ redis-cli
127.0.0.1:6379> keys *
1) "session:d473262d9ea737183cfea7327c7abb2e"
127.0.0.1:6379> get session:d473262d9ea737183cfea7327c7abb2e
"\x04\b{\x06I\"\x10_csrf_token\x06:\x06EFI\"1OVi9+6AQ8dkLwHvPbYSacBuAgtnkPKp9A+cHUBrYwEQ=\x06;\x00F"

セッションの有効期限を設定する

上記の設定だとRedisに溜まったデータが削除されず、メモリが不足してしまいます。

確認したい場合はブラウザの開発ツールでcookieを削除してページにアクセスするのを繰り返してみてください。 前のセッションが破棄されずRedisに溜まっていくのが確認できます。

先ほど作成したconfig/initializers/session_store.rbに1行追加して、 セッションの有効期限を設定しましょう。

RedisRailsSample::Application.config.session_store :redis_store, {
  servers: [
    {
      host: "localhost",
      port: 6379,
      db: 0,
      namespace: "session"
    },
  ],
  # 以下の行を追記
  expire_after: 1.minute, # 本番では1.weekなどにすると良いでしょう
  key: "_#{Rails.application.class.parent_name.downcase}_session"
}

ここでもう一度RedisとRailsを立ち上げ http://localhost:3000/tasksにアクセスしてみると、 同じようにセッションが保存されていますが、 今度は有効期限が設定されているのが分かります。

127.0.0.1:6379> keys *
1) "session:244f74bbe23995aedc7624eeafe2131d"
127.0.0.1:6379> ttl session:244f74bbe23995aedc7624eeafe2131d
(integer) 51

おわりに

以上、簡単でしたがredis-store/redis-rails を使ってみました。 次回は有名な認証機能のライブラリであるplataformatec/devise と組み合わせた挙動を確認していきたいと思います。