/shadow_model

Rails model cache with redis

Primary LanguageRubyMIT LicenseMIT

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.

Build Status Gem Version Coverage Status Code Climate Dependency Status

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

expirationSet the timeout of each cache.
update_expirationReset cache expiration after model updated (if expiration has been set).
expireatSet 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