Build Status

db_memoize

A library to cache (memoize) return values of methods in the database.

Note: when updating from version 0.1 to 0.2 you need to run a migration on the existing table, see below.

Usage in ActiveRecord models:

Example Class:

class Letter < ActiveRecord::Base
  include DbMemoize::Model

  def hello(name = 'John')
    "Hello #{name}!"
  end
  db_memoize :hello

  def bye
    'Best regards'
  end
  db_memoize :bye
end

Get Values

record = Letter.first
record.hello
=> 'Hello John!'
record.hello
=> 'Hello John!'

will call the original method only once. Consecutive calls will return a cached value.

If the method takes arguments...

record.hello('Maria')
record.hello('John')

a cached value will be created for every set of arguments.

Clear Values

To clear cached values for a single method

record.unmemoize(:hello)

To clear all cached values of one record

record.unmemoize

To clear cached values of given records for a single method

Letter.unmemoize([letter1, letter2], :hello)

To clear all cached values of given records

Letter.unmemoize([letter1, letter2])

Instead of ActiveRecord instances it's sufficient to pass in the ids of the records, too

Letter.unmemoize([23,24])

Gotchas

The cached values themselves are active records (of type DbMemoize::Value) and are saved in the database. They are also registered as an association, so you can access all of the cached values of an object like this:

record.memoized_values

This means you can also very easily perform eager loading on them:

Letter.includes(:memoized_values).all

DbMemoize by default will write log output to STDOUT. You can change this by setting another logger like so:

DbMemoize.logger = your_logger

Rake Tasks

To warmup your cache, you can pre-generate cached values via a rake task like this (only works for methods that do not take arguments):

bundle exec rake db_memoize:warmup class=Letter methods=hello,bye

Similarly, you can wipe all cached values for a given class:

bundle exec rake db_memoize:clear class=Letter

Setup

To create the required DB tables add a migration like this:

class CreateMemoizedValues < ActiveRecord::Migration
  def up
    require 'db_memoize/migrations'
    DbMemoize::Migrations.create_tables(self)
  end

  def down
    drop_table :memoized_values
  end
end

Testing

Note that db_memoize needs Postgres. To set up the database needed to run tests, this is what you can do:

~/your/path> sudo su postgresql
~/your/path> createuser >>yourusername<
~/your/path> createdb -O >>yourusername<< db_memoize_test

Updating from earlier versions

It is generally impossible to update from earlier versions and keep the cached data. DbMemoize should always be able to rerun migrations to update database structures to the latest version - feel free to add in as many migrations as you like :)