ShadowModel
A rails plugin use redis to cache models data.
Installation
Add this line to your application's Gemfile:
gem 'shadow_model'
And then execute:
$ bundle
Usage
Add this to your model class, then the models will be cached with the assigned attributes and methods after saved or updated.
shadow_model attribute_or_method1, attribute_or_method2, ..., options
And use this to retrieve the model from redis.
model = YourModelClass.find_by_shadow(primary_key)
options
expiration | Set the timeout of each cache. |
update_expiration | Reset cache expiration after model updated (if expiration has been set). |
expireat | Set the absolute timeout timestamp of each cache. |
Example
# == Schema Information
#
# Table name: players
#
# id :integer not null, primary key
# name :string(255)
# stamina :integer
# created_at :datetime not null
# updated_at :datetime not null
class Player < ActiveRecord::Base
shadow_model :name, :stamina, :cacheable_method, expiration: 30.minutes
def cacheable_method
# heavy computation here
"cacheable result"
end
end
player = Player.create(name: "player one")
shadow = Player.find_by_shadow(player.id) # retrieve from redis
shadow.is_a?(Player) # true
shadow.shadow_model? # true
shadow.readonly? # true
shadow.name # "player one"
shadow.cacheable_method # "cacheable result" (without recomputation)
shadow.reload # reload from database
shadow.shadow_model? # false
shadow.readonly? # false
Associations
has_many
You can set the shadow option of has_many association to allow shadow_model to cache all the related models.
class Game < ActiveRecord::Base
has_many :players, shadow: true
end
This will use hash data structure of redis to save the cache data, and you can retrieve all of them with one redis connection.
game = Game.create(name: "pikmin")
game.players.create(name: "player one")
game.players.create(name: "player two")
game.players_by_shadow # [#<Player id: 1, game_id: 1, name: "player one", ...>, #<Player id: 2, game_id: 1, name: "player two", ...>]
If you don't want to cache models seperately and use the association type only, you can set the association_only option to disable it.
class Player < ActiveRecord::Base
shadow_model ..., association_only: true
end