Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dsisnero/7fe747bb9ba2b5161e11 to your computer and use it in GitHub Desktop.
Save dsisnero/7fe747bb9ba2b5161e11 to your computer and use it in GitHub Desktop.

Open question for the Neo4j.rb community:

ActiveNode models allow for query chaining like so:

object.foo.bar.baz

This is a powerful way to traverse entities which builds Cypher queries under the covers. It is also currently possible to name your variables for later use like so:

object.foo(:f).bar.baz(:b).pluck(:f, 'collect(b)')

This helps you dive a bit deeper without needing to write Cypher. In fact with this syntax you can also specify a relationship variable and some options:

object.foo(:f, :r).bar(nil, nil, labels: false).baz(:b).pluck(:f, 'collect(b)')

While this is great, giving arguments to associations can often confuse people. I've been playing around with a syntax like the following, which would be equivelent to the above:

object.foo.as(:f, :r).bar.with(labels: false).baz.as(:b).pluck(:f, 'collect(b)')

If we adopt a syntax like this, it could help us simplify a chunk of our code. Obviously it's a bit more typing, but it also has the advantage of being a bit more descriptive. It also shouldn't be too hard (hopefully) to convert an existing project.

One issue that I've noted is that when you have a has_one association, there is one case where this doesn't work automatically:

object.foo.as(:f)

If foo is a has_one association it will return an object instead of returning a proxy, meaning that we can't chain the as. In cases where we're accessing the has_one association further on it the chain, there's no problem because we're expecting that there could be more than one object. An example:

object.has_many_association.foo.as(:f)

To solve this, I've thought of a couple of syntaxes:

object.foo_proxy

object.proxy_for(:foo)

The first one matches the ActiveRecord style of having some methods defined based on the association's name. The second is probably more descriptive, but is more verbose. Maybe that's fine if this is a rare case.

There's also another case where htis syntax is perhaps more awkward:

# With current syntax:
employee.manager(rel_length: 1)

# With new syntax:
employee.manager_proxy.with(rel_length: 1).first

Obviously the new syntax would be longer in this case, but perhaps it's more clear that you're working with a proxy when you explicitly call out for a proxy.

What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment