ShadowModel
A rails plugin use redis to cache models data. This will only cache the attributes and methods which you want rather than marshal the whole object. Bring with higher performance and less compatibility problems.
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