背景
Railsでredis-objectを触った私感。
別の人が導入したライブラリを仕事で使うことって、よくあると思うのですが、
「なんか複雑わからん」ってなることがよくある。
こういう時は、そのプロジェクトであーだこーだやるより、
一から自分で導入してみるといいかもしれません。
redis-objectとは
このgem。
https://github.com/nateware/redis-objects
使った感じ、
「Rubyのオブジェクトがredisにデータを保持できるようにしてあげる君」
のようなやつ。
噛み砕くと、
「Rubyオブジェクトはredisを手に入れた!」
って感じかなあ。
なんか感覚的ですが、そう感じました。
例
ユーザーが体重を記録する
各ユーザーごとに日々の体重をredisに記録したいとする。
(別にDBに保存しても良いんでしょうが、まあちょっと良い例が思い浮かびませんでした・・・)
例えばこんな感じにできる
class User < ApplicationRecord
include Redis::Objects
list :list_weight
attr_accessor :name
# 体重を保存する
def store_weight(weight)
list_weight << weight
end
end
user = User.new
user.name = "John"
user.save
user.store_weight(65)
user.store_weight(64.5)
user.store_weight(66)
user.store_weight(66.5)
user.store_weight(64)
って感じでやるとredisに以下のようなデータが保存される
# redis-cli
127.0.0.1:6379> lrange user:1:list_weight 0 -1
1) "65"
2) "64.5"
3) "66"
4) "66.5"
5) "64"
解説
include Redis::Objects
このモデルではRedis::Objectsを使います、という宣言
list :list_weight
list_weightという名前でRedis::List型のパラメータを使います、という宣言
list_weight << weight
先ほどの宣言により、このオブジェクトは
list_weight
というRedis::Listのパラメータを持ちます。
で、こうやってデータを追加すると自動でredisサーバの方に保存してくれる
user = User.new
user.name = "John"
user.save
user.store_weight(65)
user.store_weight(64.5)
user.store_weight(66)
user.store_weight(66.5)
user.store_weight(64)
で、これが実際のmainコードなんですけど、
これでuserというモデルを実体化して、
list_weightというパラメータにどんどん体重を追加していっている。
ちなみに事前にuserをsaveしているのは、
ユニークキーを発行できないとredis-objectは使えないからです。
(一般的なモデルはsaveすることで、ユニークキーidが発行されるよね)
どういうことかというと、redis側はこうやって、主キーと紐づいてデータを保存しているからです。
# redis-cli
127.0.0.1:6379> keys *
1) "user:5:list_weight"
2) "user:1:list_weight"
3) "user:4:list_weight"
4) "user:2:list_weight"
5) "user:3:list_weight"
"user:4:list_weight"
userモデルの主キー4のlist_weightパラメータ、って感じで主キーごとに保持されているんですね。
なので別に新規作成しなくても以下のようにuserが明確にできているオブジェクトならば良いです。
user = User.find(1) # 主キー"1"のユーザーを取得
user.store_weight(65)
user.store_weight(64.5)
user.store_weight(66)
こんな風にモデルが簡単にredisのデータをもてるってことです。
普通にパラメータにアクセスすればRedis::Listでデータにアクセスできるので
このページにあるような関数で色々加工なりすることも簡単です
https://www.rubydoc.info/github/nateware/redis-objects/Redis/List
user.list_weight.to_s # stringにして全件取得する
user.list_weight.range(0, 3) # 先頭から4つだけ取得する
雑感
ということで、自分で再構築してみると、時間はかかりますが、まじでわかりやすいかともいます。
なんせ、他者様の描いたコードは緻密な経験や試行錯誤の結果なので、
いきなり結果だけ見ても見えづらいものです。