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?