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.
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 jruby
To check if everything worked as expected type
ruby -v which should return a message like the following:
$ ruby -v jruby 184.108.40.206 (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
-O option skips ActiveRecord which we do not need as all functionality for database handling is provided by the
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
root :to => 'posts#index'
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_one class methods generate convenience methods for creating and traversing nodes. However they should not be confused with
has_one assume relationships to the same class and not to different classes.
As we want to create a relationship from
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 (
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.
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 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.
There are many other resources available that provide additional guidance:
- Neo4j 2.x Documentation
- Neo4j 1.3.1 Documentation
- Paperclip for Neo4j
- Carrierwave for Neo4j
- Devise for Neo4j (only works with Devise 1.x)
- JetStrap, a bootstrap building tool
The gems listed are a little bit dated and require some work to get them set up.