Cache.rb - the smallest feasible database

Published
2012-12-26
Tagged

I have a bunch of little glue applications that involve my interacting with OmniFocus or similar apps and displaying data on my desktop. As an example, consider my previous post turning OmniFocus into some sort of Kanban-esque planner for my projects.

Most of my projects end up looking something like this:

Of course, I may not want OmniFocus running all the time. Without checks, accessing OmniFocus through applescript (my usual channel) when it’s not running will just cause it to open - which isn’t always what I want. You can put in a check easily enough - I’m doing this in ruby via rb-appscript:

1
if !app('System Events').processes[its.name.eq 'OmniFocus'].get.empty?
2
   # Code goes here...
3
 end

This is fine if you don’t mind that the default action when OmniFocus is closed being “do nothing”. But what if every time you queried OmniFocus you cached the data?

The new model of program

In this model, our program takes data from OmniFocus and chucks it in a file for safe-keeping. A second program can then format this data as required and output it. If OmniFocus isn’t running, the first program can quit silently, and our display program will just use the last fetched data:

Enter jcache.rb

I found myself doing this twice, which is a good sign that I should be making a separate library and doing it once. That turned into the cachejcache gem, which I won’t be pushing to rubygems.org because this is a tiny, tiny gem that’s trivial to make once you know you need it. But for me, local gems are the best way to package up little libraries of code that I use over and over again (as long as I never need to use the “official” cache gem).

jcache.rb is pretty simple to use once it’s installed (more on that later):

1
require 'jcache'
2
3
c = Cache.new 'foo'
4
c['key'] = 3
5
c.save

This will save the cache to file in ~/.cache/foo.yaml (by default). If you check out that file any time, you’ll see a pretty YAML file:

1
---
2
:key: 3

There’s actually an easier way to view this:

1
> cache foo
2
Contents of cache foo:
3
4
---
5
:key: 3

This is obviously a pretty tiny example, but it scales up pretty effectively. Each cache is simply a hash of key-value pairs stored in a file.

Installation

You can check out jcache.rb herehere on github, or include it in your gemfile:

1
gem 'jcache', "~>; 0.2.0", git:"git://github.com/jyruzicka/jcache.git"

I guess you could also install it from github:

1
git clone git://github.com/jyruzicka/jcache.git
2
cd jcache
3
gem build jcache.gemspec
4
gem install jcache-1.0.0.gem #may be different depending on current version

[UPDATE] It turns out that if you run gem update and you have a gem installed from a local source whose name matches a published gem, rubygems will overwrite your gem. So this project is now known as JCache to prevent namespacing problems.