RailsにRedisを導入した際のメモ

redisライブラリの導入

Gemfileに以下を追加する。

1
2
gem 'redis'
gem 'hiredis-client'

Railsのキャッシュの設定

  • Railsのキャッシュのデフォルトの保存先はtmpファイルになっている(キャッシュストアの設定
  • Redisを使うように変更するには以下のようにする

対象ファイル:config.enveronments/production.rb

変更内容:

1
2
3
4
config.cache_store = :redis_cache_store, {
url: ENV['REDIS_URL'],
ssl: true, # この行はAmazon ElastiCache For Redisの場合のみ。ローカルのDocker開発環境の場合は不要
}

ENV['REDIS_URL']について

ENV['REDIS_URL']については、それぞれ以下のように設定する。

Amazon ElastiCache For Redis の場合

redis://hoge.serverless.apne1.cache.amazonaws.com:6379/0

ローカルのDocker開発環境の場合

redis://redis:6379/0

docker-compose.ymlに以下のように追記する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
web:
environment:
REDIS_URL: 'redis://redis:6379/0'
depends_on:
- redis

redis:
image: redis:latest
ports:
- "6379:6379"
volumes:
- redis-data:/data

volumes:
redis-data:
driver: local

キャッシュを利用するコード

上記の設定完了後、以下のコードでキャッシュが効くようになる。

1
2
3
4
5
6
key = "cache_count_" + params[:id]
result = Rails.cache.fetch(key, expires_in: 5.minutes) do
# キャッシュがなければここが実行される
count = get_count(params[:id])
count
end

と、基本的にはこれだけでOK。

注意点

  • Redisでは正規表現を使ってキャッシュを削除することができる
  • 例えばRails.cache.delete_matched('cache_count_*')
  • ただし、Amazon ElastiCache For Redis は正規表現を使ってキャッシュを削除することができない
  • Amazon ElastiCache For Redis はクラスター構成となっていて、キャッシュの保存先が分散されているため
  • 以下のエラーが発生する
  • CROSSSLOT Keys in request don't hash to the same slot

リストやハッシュをキャッシュする場合

  • 上記の設定では、キャッシュの対象は文字列のみ
  • リストやハッシュをキャッシュする場合は、$redisインスタンスを直接利用する必要がある

$redisの設定

config/initializers/redis.rbを作成し、以下のように記述する。

1
$redis = Redis.new(url: ENV['REDIS_URL'])

リストをキャッシュする場合

1
2
$redis.lpush('list_key', 'value')
$redis.lrange('list_key', 0, -1)

注意点

sslを有効にする場合、Rails.cacheではssl: trueのオプションがあったが、$redisではurlrediss://を指定する必要がある。
例えば、rediss://hoge.serverless.apne1.cache.amazonaws.com:6379/0とすると、sslが有効になる。

Railsでアプリログのフォーマットを変更する方法

Railsでアプリログのフォーマットを変更する方法です。

以下の2ファイルを追加・修正します。

(追加)app/lib/local_dev_log_formatter.rb

1
2
3
4
5
6
7
class LocalDevLogFormatter < ActiveSupport::Logger::SimpleFormatter
def call(severity, timestamp, progname, msg)
formatted_severity = sprintf("%-5s", "#{severity}")
formatted_time = timestamp.strftime("%Y-%m-%d %H:%M:%S.") << timestamp.usec.to_s[0..2].rjust(3)
"[#{formatted_severity} #{formatted_time} ##{Process.pid}] #{msg}\n"
end
end

(修正)config/environments/development.rb

1
2
3
4
5
6
7
8
9
Hoge::Application.configure do

# 中略

config.log_formatter = LocalDevLogFormatter.new # 日時を出力するためにカスタムフォーマッターを指定
logger = ActiveSupport::Logger.new("log/#{Rails.env}.log", 5, 100 * 1024 * 1024)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end

app/lib配下に配置することとconfig.loggerの方にも設定が必要なところが分からなくてハマりました。。

【RSpec】current_companyのメソッドで特定の値を返す

1
2
3
4
before do
company.created_at = Time.local(2022, 12, 02, 0, 0, 0)
allow_any_instance_of(HogeController).to receive(:current_company).and_return(company)
end

いつもモックやスタブではallow(hoge).to receive(:fuga).and_return(piyo)の書き方でやってたので、それがうまく効かなくてハマりました。。

以上です。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×