Skip to content

Instantly share code, notes, and snippets.

@ssaunier
Created September 6, 2017 13:22
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ssaunier/aa864340b07748c4f92a5345717ce1e9 to your computer and use it in GitHub Desktop.
Save ssaunier/aa864340b07748c4f92a5345717ce1e9 to your computer and use it in GitHub Desktop.
Quick caching in Rails (backed by Redis, with Heroku Redis Cloud add-on)

Add this line to your Gemfile and run bundle install

# Gemfile
gem "redis"

Create a new initializer to have a global $redis variable at hand:

touch config/initializers/redis.rb
# config/initializers/redis.rb
$redis = Redis.new

url = ENV["REDISCLOUD_URL"]

if url
  Sidekiq.configure_server do |config|
    config.redis = { url: url }
  end

  Sidekiq.configure_client do |config|
    config.redis = { url: url }
  end
  $redis = Redis.new(:url => url)
end

Then create a new Cache service:

mkdir -p app/services
touch app/services/cache.rb

Open this cache.rb file and paste the following code:

class Cache
  include Singleton
  EXPIRE = 1.week
  
  def get(*args, &block)
    the_key = key(*args)
    if (value = redis.get(the_key)).nil?
      value = yield(self)
      redis.set(the_key, Marshal.dump(value))
      redis.expire(the_key, expire)
      value
    else
      Marshal.load(value)
    end
  end
  
  def key(*args)
    "cache:#{args.join(":")}"
  end
end

Then to use the cache on an API for instance:

require "open-uri"

url = "https://api.github.com/users/ssaunier"
result = Cache.instance.get(:api_user, url) do
  JSON.parse(open(url).read)) # Expensive (long) call to cache
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment