Basic usage of Riak in Rails

OK, you’re convinced that Riak is a great database, now you want to use it in your Rails 3 app. You should really have a look at the advices from Basho, and especially the Riak with Rails slides from Sean Cribbs.

So first, let’s install the rich ruby client for Riak, ripple, built on top of riak-client. Simply add the following lines to your Gemfile:

gem 'ripple'    #=> riak orm ; installs "riak-client" as a dependency
gem 'excon'     #=> faster http
gem 'yajl-ruby' #=> faster json

…and of course run bundle command.

Then generate your ripple config with:

rails generate ripple

Optionnaly you can configure the config/ripple.yml file. With the environment I used in my previous article, I had to change the riak server’s port (default is 8098, I had to change it to 8091, 92 or 93 for my development cluster).

Then generate a first model:

rails generate ripple:model Article title:string content:text

The generated app/models/article.rb looks like this:

class Article
  include Ripple::Document
   
  property :title, String
  property :content, String
end

You can optionnaly add timestamps! if you want to have created_at/updated_at fields updated automatically by ripple.

You can now test everything runs fine in a rails console session:

>> Article.all
=> []
>> Article.create(:title => "A shiny title", :content => "Lorem ipsum blah bleh")
=> <Article:Fp1RZWPRDcDLLjDv8aJ0t3p0C5i created_at=2011-04-23 16:25:13 UTC title="A shiny title" content="Lorem ipsum blah bleh" updated_at=2011-04-23 16:25:13 UTC>

Looks ok, but the key isn’t so pretty. After a quick search on google, it appears that this key is auto-generated by Riak if not provided by the client, and it’s pretty easy to define your own key format. I personnaly wanted the creation date and the title in the key:

def key
  @key ||= "#{created_at.strftime("%Y%m%d%H%M%S")}-#{title.parameterize}"
end

Now it looks better:

>> reload!
Reloading...
=> true
>> Article.create(:title => "A shiny title", :content => "Lorem ipsum blah bleh")
=> <Article:20110423182948-a-shiny-title created_at=2011-04-23 16:29:48 UTC title="A shiny title" content="Lorem ipsum blah bleh" updated_at=2011-04-23 16:29:48 UTC>

It seems there’s a tiny problem with Article.all, since it doesn’t contain the newly created item. I’ll ask about that on the riak mailing list, but it seems Riak client does a bit of caching. If you really need it, reset the cache by hand, it’s ugly but it works:

>> Article.all
=> []
>> Ripple.client.instance_variable_set(:@bucket_cache,nil)
=> nil
>> Article.all
=> [<Article:20110423183635-a-shiny-title created_at=2011-04-23 16:36:35 UTC title="A shiny title" content="Lorem ipsum blah bleh" updated_at=2011-04-23 16:36:35 UTC>]

Now, what about the controller side ? This is where Rails 3 has become a powerful solution, it’s database agnostic. I generated a scaffold with the 7 standard crud actions:

rails generate scaffold Article title:string content:text

It works for 6 of the 7 elementary actions, but I must admit I had a tiny problem with the destroy action, because of a bug in ActiveModel. It’s described here with a workaround, so I added those 2 lines in my Article model:

  def validation_context=(value); end
  def initialize(*args); errors; super(*args); end

I’m not really sure which impact it will have on my validations, but validations and links between objects are for the next article. That’s all for today, hope this article will be useful for some of you!

edit: replaced ‘curb’ gem by ‘excon’