この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
Ruby on RailsにてRedisに登録するデータを扱う際に、通常のActiveRecordのModelのようにデータを操作できる dm-redis-adapter を紹介したいと思います。これを使うと、Redisに登録するデータを、以下のように扱うことができます。
- 一つのModelを一レコードのように扱い、複数のプロパティを持たせて登録する
- 登録するデータにidを持たせ、自動的にインクリメントした値を登録する
- モデル名.create のように、ActiveRecordと同じようなメソッドを使用してデータを操作する
以下に、Gemの使用方法やソースの例を記述します。
Gemの使用準備
dm-redis-adapterをRuby on Railsで扱う方法についてです。データの登録先としてRedisを使うので、予めインストールしておいてください。(もしくはサーバなどに用意しておく)
1.Gemのインストール
Gemfileに以下を記述し、$ bundle install します。
gem 'redis-objects'
gem 'dm-core'
gem 'dm-redis-adapter'
2.接続情報とRedisオブジェクトの作成
/config/initializersフォルダ内に、Redisの接続情報とオブジェクトを作成するためのソースを作成します。今回は「redis.rb」というファイルを作成し、以下のように記述しました。
/config/initializers/redis.rb
Redis.current = Redis.new(:host => '127.0.0.1', :port => 6379)
上記例は、ローカルでRedisを実行する場合のものです。(確認はしてませんが)サーバなど別マシン上でRedisを実行する場合は、「:host」にそのマシンのIPを指定してください。
Modelの定義
Redisの登録するデータについて、Modelを定義します。今回はUserモデルを作成し
- idを保持し、idにて検索できるようにする
- 項目として「name」「email」を持つようにする
ようにしました。以下、Userモデルのソースです。
/app/models/user.rb
DataMapper.setup(:default, {:adapter => "redis"})
class User
include Redis::Objects
include DataMapper::Resource
property :id, Serial
value :name
value :email
end
User.finalize
一番上、一番下の行は「お約束」のようなものです(笑)。重要なのは3〜11行目(つまりUserクラス)で
- UserクラスはActiveRecordを継承せず、Redis::Object、DataMapper::Resourceをincludeする
- 7行目でidをプロパティとして定義し、AutoIncrementさせるため「Serial」で定義する
- 保持したい項目(今回はname、email)を「value」として定義する
を行っています。
Redisへの登録・参照・更新・削除
上記のUserモデルを使用して、データを操作します。今回はRspecにて記述しました。RSpecを実行する前に、以下のコマンドでRedisを起動します。
$ radis-server
/spec/models/user_spec.rb
require 'rails_helper'
RSpec.describe User, :type => :model do
include Redis::Objects
before do
Redis.current.flushall
end
after do
Redis.current.flushall
end
describe 'User Data' do
before do
user = User.create
user.name = 'TestUser'
user.email = 'test@ggg.com'
@id1 = user.id
user = User.create
user.name = 'TogoJuzo'
user.email = 'duke@ggg.com'
@id2 = user.id
end
it 'should find.' do
user = User.first(id: @id1)
name = user.name.value
email = user.email.value
expect(name).to eq('TestUser')
expect(email).to eq('test@ggg.com')
user = User.first(id: @id2)
name = user.name.value
email = user.email.value
expect(name).to eq('TogoJuzo')
expect(email).to eq('duke@ggg.com')
end
it 'should update.' do
user = User.first(id: @id2)
user.email = 'm16@ggg.com'
updated = User.first(id: @id2)
email = updated.email.value
expect(email).to eq('m16@ggg.com')
end
it 'should delete.' do
user = User.first(id: @id1)
user.destroy
user = User.first(id: @id1)
expect(user).to be_nil
end
end
end
データの登録
15〜25行目のbeforeの中で、Userモデルを登録しています。このbeforeを実行すると、Redisには以下のようにデータが登録されます。
$ redis-cli
127.0.0.1:6379> keys *
1) "user:1:email"
2) "user:2:name"
3) "users:id:all"
4) "user:1:name"
5) "user:2:email"
6) "users:id:serial"
Redisのキーとして「user:idの値:項目名」が登録され、それぞれが別レコードとして保持されていることが分かります。登録されている値を確認してみると、以下のようになります。
127.0.0.1:6379> get user:1:email
"test@ggg.com"
127.0.0.1:6379> get user:1:name
"TestUser"
この「user:idの値:項目名」をキーとして登録していることで、dm-redis-adapterがRedisに登録するデータをModelのように扱うことを実現しているようです。
データの参照
27〜41行目で、データの参照を行っています。firstメソッドの引数に、対象のidを指定することで、ActiveRecordのModelに近い形で参照しています。
データの更新
43〜50行目で、データの更新を行っています。注意すべき点は、項目の値を書き換えた後(45行目)、updateなどの更新のためのメソッドを呼び出していないことです。
データの削除
52〜58行目で、データの削除を行っています。こちらもdestroyメソッドを使用し、ActiveRecordのModelに近い形で実現しています。注意すべき点は、destoryしたデータはfirstでは取得出来ないが、Redis上では物理的には削除されていないことです(redis-cli上で確認すると、データが存在する)。Redis内のキー「users:id:all」「users:id:serial」を使用して、dm-redis-adapterが削除扱いとしていると思われるのですが、現時点では未確認です。
まとめ
dm-redis-adapterを使い、key-valueの組み合わせであるRedis上のデータをModelに近い形で扱うことができました。