Using Neo4j with Rails 3.2

Using Neo4j with Rails 3.2

Neo4j is a NoSQL graph database written in Java. This means that you work with nodes and relationships rather than fixed tables with a schema. Nodes can easily be mapped to Ruby object and relationships seen as references to other objects. This article will show how to utilize Neo4j to build a simple blog application. While this is not a typical application for a graph database it will show how the database can be used in conjunction with Rails.

Prerequisites

The neo4j gem we will be using in this article requires JRuby. If you are using RVM you can install JRuby by typing rvm install jruby. Make sure you have at least JRuby 1.6.2 installed, otherwise Rails will not work properly.

You can then switch to JRuby by using rvm use:

rvm use jruby

To check if everything worked as expected type ruby -v which should return a message like the following:

$ ruby -v
jruby 1.6.7.2 (ruby-1.8.7-p357) (2012-05-01 26e08ba) (Java HotSpot(TM) 64-Bit Server VM 1.7.0_05) [linux-amd64-java]

As you can see, JRuby 1.6 is compatible with Ruby 1.8.7. If you want to make use of the latest features in Ruby 1.9 you need to upgrade to JRuby 1.7 which is, at the time of this writing only available as a preview version.

Generate a Rails Application

Now that everything is set up we can create a new Rails project which we will name 'neo_blog'.

gem install rails
rails new neo_blog -m http://andreasronge.github.com/rails3.rb -O
cd neo_blog
bundle

Note: The -O option skips ActiveRecord which we do not need as all functionality for database handling is provided by the neo4j gem.

Creating a blog

We can now use the standard generators of Rails. For a blog application we will need a Post model, a controller and views: A perfect job for the scaffold generator.

rails generate scaffold Post title description content:text published_at:date

This creates several files. The most interesting is the new post model which inherits from Neo4j::Rails::Model. Also note that there are no migration you have to run as Neo4j is schema-less.

class Post < Neo4j::Rails::Model
  property :title, :type => String
  property :description, :type => String
  property :content, :type => String
  property :published_at, :type => Date
end

We should then configure the routes to default to the post controller and delete public/index.html

root :to => 'posts#index'

Adding comments

A blog certainly cannot live without users being able to comment on your posts. We need to add another resource to our project:

rails generate scaffold comment author email content:text

We now have a comment model that we need to associate with our post model. Neo4j provides Neo4j::Rails::Relationship to handle relationships between Neo4j nodes. Neo4j::Rails::Relationship is ActiveModel compatible and implements some ActiveRecord methods, which means you can run validations on it.

Relationships are handled a bit differently than in ActiveRecord. The has_n and has_one class methods generate convenience methods for creating and traversing nodes. However they should not be confused with has_many or has_one! Both has_n and has_one assume relationships to the same class and not to different classes.

As we want to create a relationship from Post to Comment we need to specifically tell Neo4j to create the relationship from posts to comments. The .to methods accepts a class as parameter and defines which class is referenced.

class Post < Neo4j::Rails::Model
  has_n(:comments).to(Comment)
end

With that line in the post model we can easily add new comments to a post. You can try the following on the rails console (rails c)

p = Post.first
c = Comment.create(:content => "Nice post!")
p.comments << c

Now in order to associate comments to a post we need to change the create action of the comments controller.

def create
    @post = Post.find(params[:id])
    @comment = @post.comments.build(params[:comment])
    [..]
end

From there you can go ahead an customize the views and CSS to style the blog. JetStrap, a recently released interface-builder for Twitter Bootstrap, makes it easy to create good looking web interfaces. Also have a look at the Github Project of the blog we build here.

Neo Blog with Bootstrap

Viewing the Neo4j admin web interface

Neo4j comes with a nice web interface which allows you to query the database and browse through the graph. The neo4j-admin gem will start the web interface on port 7474 once your app is started.

gem 'neo4j-admin', group: :development

Note that I added the gem to the development group, so that it will not start in production. When you now restart your app and access http://localhost:7474 on your browser you will see the Neo4j web interface.

Neo4j admin interface on localhost:7474

Conclusions

The neo4j gem easily allows you to replace ActiveRecord and use Neo4j as a fast graph-based database backend. The blog application shown in this article does certainly not show a typical use case for graph databases where you store highly interconnected data, but serves as an entry point for further work with Neo4j. There are many ways in which the blog application could be extended to make use of the features that a graph database has to offer, some of which will be discussed in a later article.

Andreas Ronge, the author of the Neo4j gem, has developed a well-tested and feature rich gem which is easy to use. The documentation is not always up to date, but there are enough resources available to help with that.

Other Resources

There are many other resources available that provide additional guidance:

The gems listed are a little bit dated and require some work to get them set up.