From 0551fb217f5f4c4c62acba8a8972c4fd56996fc9 Mon Sep 17 00:00:00 2001 From: Aseem Kishore Date: Mon, 10 Sep 2012 22:10:06 -0400 Subject: [PATCH] Fix transform to properly handle paths and maps. And add a test (that failed before this) to test returning paths. Sweet! --- lib/util.coffee | 41 +++++++++++++++++++++++++++++------------ test/cypher._coffee | 19 +++++++++++++++++++ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/lib/util.coffee b/lib/util.coffee index fec573c..f3fb51c 100644 --- a/lib/util.coffee +++ b/lib/util.coffee @@ -105,28 +105,42 @@ exports.adjustError = (error) -> # transforms it or its subvalues into the appropriate Node/Relationship/Path # instances. returns the transformed value. exports.transform = transform = (val, db) -> + # ignore non-objects: + if not val or typeof val isnt 'object' + return val + # arrays should be recursed: if val instanceof Array return val.map (val) -> transform val, db - # ignore non-neo4j objects: - # (XXX this means we aren't recursing hash maps for now! fine for now.) - if not val or typeof val isnt 'object' or not val.self - return val - # inline requires to prevent circular dependencies: Path = require './Path' Node = require './Node' Relationship = require './Relationship' - # relationships have a type property: - if typeof val.type is 'string' + # we want to transform neo4j objects but also recurse non-neo4j objects, + # since they may be maps/dictionaries. so we detect neo4j objects via + # duck typing, and assume all other objects are maps. helper: + hasProps = (props) -> + for type, keys of props + for key in keys.split '|' + if typeof val[key] isnt type + return false + return true + + # nodes: + if hasProps {string: 'self|traverse', object:'data'} + return new Node db, val + + # relationships: + if hasProps {string: 'self|type|start|end', object:'data'} return new Relationship db, val - # paths have nodes and relationships: - # (XXX this doesn't handle fullpaths, but we don't return those yet.) - if val.nodes and val.relationships + # paths: + # XXX this doesn't handle fullpaths for now, but we don't return those + # anywhere yet AFAIK. TODO detect and support fullpaths too? + if hasProps {string: 'start|end', number: 'length', object:'nodes|relationships'} # XXX the path's nodes and relationships are just URLs for now! start = new Node db, {self: val.start} end = new Node db, {self: val.end} @@ -138,9 +152,12 @@ exports.transform = transform = (val, db) -> return new Path start, end, length, nodes, relationships - # the only other type of neo4j object is a node: + # all other objects -- treat as maps: else - return new Node db, val + map = {} + for key, subval of val + map[key] = transform subval, db + return map exports.serialize = (o, separator) -> JSON.stringify flatten(o, separator) diff --git a/test/cypher._coffee b/test/cypher._coffee index dff0015..9675032 100644 --- a/test/cypher._coffee +++ b/test/cypher._coffee @@ -120,5 +120,24 @@ assert.ok typeof results[0]['collect(n)'][0] 'object' assert.equal results[0]['collect(n)'][0].id, user0.id assert.equal results[0]['collect(n)'][0].data.name, user0.name +# test: can return paths +results = db.query """ + START from=node({fromId}), to=node({toId}) + MATCH path=shortestPath(from -[:follows*..3]-> to) + RETURN path +""", {fromId: user0.id, toId: user6.id}, _ +assert.equal results.length, 1 +assert.ok typeof results[0]['path'], 'object' +assert.ok typeof results[0]['path'].start, 'object' +assert.ok typeof results[0]['path'].end, 'object' +assert.ok results[0]['path'].nodes instanceof Array +assert.ok results[0]['path'].relationships instanceof Array +assert.equal results[0]['path'].length, 2 +assert.equal results[0]['path'].start.id, user0.id +assert.equal results[0]['path'].end.id, user6.id +assert.equal results[0]['path'].nodes.length, 3 +assert.equal results[0]['path'].nodes[1].id, user3.id +assert.equal results[0]['path'].relationships.length, 2 + # give some confidence that these tests actually passed ;) console.log 'passed cypher tests'