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
Switching Ruby versions

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]
JRuby version with compatibility information

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
Using an application template

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
Generate a new scaffold for posts

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
Post model (app/models/post.rb)

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

root :to => 'posts#index'
Set default route to PostController#index (config/routes.rb)

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
Adding a scaffold for comments

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
Add a new comment to a post

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
CommentsController#create

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 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
Adding neo4j-admin in Gemfile

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 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.

Comments


Avatar
Andreas Ronge – about 2 years ago

Great article !

Notice that when using has_n and has_one you can have relationships to any class. The only limitation is that Rails sometimes needs know it when creating new nodes (e.g using accepts_nested_attributes_for).

The documentation should be rather up to date. I've moved the docs to github wiki, e.g.
Neo4j::Persistence

Avatar
Mark McCraw – almost 2 years ago

A few issues I had that might help anyone else following this tutorial:

When generating the application, the template referenced by the -m option didn't seem to work for me. I'm not terribly familiar with these templates, but doing a little legwork, I noticed that http://andreasronge.github.com/rails3.rb is a one-liner that pulls in http://andreasronge.github.com/default.rb. Most of default.rb didn't work for me. The gemfile substitutions didn't do anything and the 'require' additions to config/application.rb didn't seem to work. I was able to figure out the intent pretty easily and add them, though.

Even after that, I ran into issues with the version of neo4j when I tried to run the scaffolding for the Post model. It just failed spectacularly, and rather than try to figure out why, I lazily started by just looking for a newer version of neo4j than 1.3.1. It turns out there is! (2.2.3, as of the time of this comment), and updating my Gemfile with that made things work.

That's as far as I've gotten for now, and all the time I'll have today to work on it. When I pick it back up, I'll post other notes if I run into more issues.

Thanks for the tutorial!

Avatar
Mark McCraw – almost 2 years ago

The admin console part also didn't work for me at first. I went and found the readme for the gem project on github (https://github.com/andreasronge/neo4j-admin) and noticed that config/application has to contain the following line as well:

require 'neo4j-admin/railtie'

After adding this and restarting the app, things work as described

Avatar
Craig Taverner – over 1 year ago

Mark, I found that the template at andreasronge.github.com/neo4j/rails.rb worked for me.
This is described at andreasronge.github.com/neo4j/ although I first found it mentioned in a very useful google groups discussion at https://groups.google.com/forum/?fromgroups=#!searchin/neo4jrb/devise/neo4jrb/WPCZ5C_gVbE/GPuFvbcS9LQJ where Chris F. shows how to get devise-neo4j working (authentication). Very cool.

Anyway, the rails command that worked for me was:

rails new neo_blog -m http://andreasronge.github.com/neo4j/rails.rb -O
Avatar
Craig Taverner – over 1 year ago

Following on from Marks first comment, I found this command worked:

rails new neo_blog -m http://andreasronge.github.com/neo4j/rails.rb -O

This is referenced from Andreas page at http://andreasronge.github.com/neo4j/

Avatar
Craig Taverner – over 1 year ago

I've found that the code example has an error. I cloned the project at github.com/geekproject/neo_blog, did a bundle update (which moved the neo4j.rb gem from 2.0.1 to 2.2.3 and rails from 3.2.8 to 3.2.11). But when trying the app out, I cannot add comments to the blog, because line 43 of the comments_controller (create method) returns nil from the call:

@post = Post.find(params[:id])

Looking at the partials I am not able to see how params[:id] was supposed to be set. The comments/_form partial is called from posts/show.html.erb using a line like:

<%= render 'comments/form' %>

Since this is in the posts/show view, I assume rails is supposed to magically set the params[:id], but the params I get in the comments creation contain only the comments form fields:

{"utf8"=>"?", "authenticity_token"=>"xxx",
"comment"=>{"author"=>"me",
"email"=>"my@mail",
"content"=>"Some text"},
"commit"=>"Create Comment"}

I must assume the original code worked fine with older gems, so what could have changed (or is there a bug in the example code on github?)

Avatar
Craig Taverner – over 1 year ago

And after adding the admin console, if I try view the graph view in that, I get the error:

java.lang.NoSuchMethodError:
org.neo4j.graphdb.traversal.Evaluators.toDepth(I)
Lorg/neo4j/graphdb/traversal/Evaluator;
Avatar
Fabian Becker – over 1 year ago

Hi Craig,
params is a hash automatically available in Rails. See Rails Parameters.

I'll look into the other errors.

Avatar
– over 1 year ago

Hello!
I am trying to create my first application with use of Ruby on Rails (3.2.13) and Neo4j.
I have a problem with a person:) I have created Person model class and People Controller (with use of Scaffolding). I can create nodes of Person (I can see it in Neoclipse), but when I try to find a person with given name, RoR gives me the answer, that there is no such a person.
I have tested it with other classes, like place, device etc. and it works perfectly.
May it be a problem with different pluralization of a word “person”? Do you know how to fix this problem?

Avatar
– about 1 year ago

You can use Neo4j-friendship gem:
https://rubygems.org/gems/neo4j-friendships

Avatar
Brian Underwood – 25 days ago

FYI we've also just released a 3.0.0 of the gem which completely changes the API and also doesn't require jRuby anymore! Check out our wiki:

https://github.com/neo4jrb/neo4j/wiki/Neo4j.rb-v3-Introduction

And this intro screencast:

https://www.youtube.com/watch?v=bDjbqRL9HcM

First sign in through Github or Twitter