Written by Chris Grigg
After hundreds of hours of work from numerous contributors over the past year, Neo4j.rb, the ActiveRecord replacement for Ruby on Rails and Rack frameworks, has been released! This new version, a complete rewrite of the entire gem, is an exciting relaunch that offers the perfect experience for anyone looking to use Neo4j in their app. You can find it on Github at https://github.com/neo4jrb/neo4j and on Rubygems at https://rubygems.org/gems/neo4j.
My name is Chris Grigg, one of the project’s maintainers, and in this post, I’ll introduce you to some of 3.0’s new and interesting features.
Left to right: Chris Grigg, Andreas Ronge, Brian Underwood
While Neo4j.rb 2.3 was extremely powerful, its requirement of using JRuby limited deployment options, to say nothing of the complications involved in testing and gem compatibility. 3.0 makes this a thing of the past, with support for Neo4j REST Server using Ruby MRI. If you prefer JRuby and the embedded database, that is still supported; switching between the two involves changing a few simple lines in your application’s config but otherwise, none of your app’s code will have to change. Thanks to this, deploying to the PaaS of your choice is finally possible.
Revolutionary Cypher DSL
Every part of the gem has been overhauled to provide a better combination of ActiveRecord-like syntax and increased power when compared to version 2.3. Nowhere is this more evident than in the new Cypher query DSL, referred to within the gem as QueryProxy. Let’s take a look at a few examples.
Imagine a graph of objects related to college class scheduling. It includes nodes for students, teachers, and lessons, each with corresponding models of the same names and associations between them. Using QueryProxy, matches that would be very complex in SQL and maybe even a little long in Cypher are generated easily with Ruby.
Assuming “student” is a Student node, we can see all of their lessons with one easy query, as any Rails user would expect:
But what if you want to find all of the teachers of all of their lessons? You can chain the Lesson model’s “teachers” association and the server will perform a single Cypher match to generate the response:
How about finding all of the lessons taught by teachers, age 43? Assuming an “age” property on Teacher, that’s just as easy.
Matching relationship properties couldn’t be easier. Want to know all young teachers, age less than 30, who have students in lessons with grades of A+? Chain associations on class methods, call “where” and specify the lesson relationship, and then tell it to give you back the matching teachers!
Teacher.as(:t).where(“t.age < 30”).lessons.students(:student, :lesson_rel).where(“lesson_rel.grade: ‘A+’”).pluck(:t) # generates the impressive Cypher: # MATCH (t:`Teacher`), (lesson:`Lesson`), (t)-[rel1:`lessons`]->(lesson), (lesson)<-[lesson_rel:`lessons`]-(student:`Student`) WHERE t.age < 30 AND lesson_rel.grade = ‘A+’
Queries like these in SQL would be extremely complex and slow; as they grow in complexity, the likelihood of being able to implement them without having a DBA on staff goes down. Neo4j.rb 3.0 lets any Ruby developer unlock the power of Cypher without having to know more than the basics of the query language. When you’re ready to move into move advanced queries, the full Cypher language is already available through the Query class in the neo4j-core class, which is automatically included when you use Neo4j.rb.
A New Paradigm: Relationship Models for Relationship Objects
As we know, relationships in Neo4j are objects and very similar to nodes: they have properties, they can be matched, they can be created and destroyed. With Neo4j.rb 3.0, we introduce ActiveRel, the relationship wrapper, to let you create models for relationships. With these, you can keep complex relationship code away from your nodes. ActiveRel models share syntax with node models, so you can take advantage of the same validations, callbacks, and custom methods on classes and instances, just like you would with models in vanilla Ruby on Rails.
Neo4j-flavored Enumerable Methods
Methods such as count, include?, empty?, exists? and many more can be called on query proxy chains to evaluate the results entirely in Neo4j. Methods such as :each_rel and :each_with_rel can be called to get direct access to relationships without making extra queries.
Friendly for Rails Developers
In addition to adding features, the entire gem has been overhauled to offer a lower learning curve for ActiveRecord users making the switch. Everything is more natural, feels more predictable, and better documented.
Committed Maintenance, a Growing Community
sponsored co-maintainer Brian Underwood and I to travel from the US to Malmö, Sweden to work alongside the gem’s creator, Andreas Ronge, in the Neo Technology office. Along with polishing up the alpha version into the release candidate, we discussed future plans and our hopes for both the gem and Neo4j. We’re looking forward to hearing from you, seeing what you create with it, and working with you to make this tool even better as time goes on.