rom-rb / rom-neo4j

Experimental integration of Neo4j with Ruby Object Mapper
23 stars 2 forks source link

Accessing relationships causes an error #1

Open smackesey opened 9 years ago

smackesey commented 9 years ago

There is some sort of issue with the monkey-patching of neo4j-core. Given this code:

setup.relation(:records) do
  matches '(n:stmpd)'
  returns 'n'

  def by_type(type)
    where("'#{type}' IN n.type")
  end

end

class Record

  def initialize(res)
    @node = res[:n]
  end

  def d
    @node.props
  end

  def rels
    @node.rels
  end

end

class RecordMapper < ROM::Mapper
  relation :records
  register_as :entity
  model Record
end

rom = ROM.finalize.env

This throws an error:

x = rom.relation(:records).by_type('article').as(:entity).first.rels

The error is:

NoMethodError: undefiend method `result` for {:result => CypherRelationship 2081}:Hash

maetl commented 9 years ago

Good catch, thanks!

The monkey-patch was an exploratory attempt to understand the integration with transproc which doesn’t fully support mapping structs (see: https://gist.github.com/maetl/df441f02370ec3100423). It definitely needs to be replaced with something more robust.

I can reproduce the behaviour with the movies dataset as follows:

r = rom.relation(:records).by_title('The Matrix').to_a

This triggers:

undefined method `result' for {:result=>CypherRelationship 24930}:Hash (NoMethodError)

Commenting out #require 'rom/neo4j/support/core_ext' from the Gem results in the following:

[CypherRelationship 24930, CypherRelationship 24931, CypherRelationship 24932, CypherRelationship 24933, CypherRelationship 24937, CypherRelationship 24934, CypherRelationship 24935, CypherRelationship 24936]

Raw structs do partially work with ROM::Mapper, but are unlikely to compose well in many cases. I’m considering writing a custom mapper extension to deal directly with the neo4j-core Gem, but if possible, I’d like to solve the problem in a more simple way by mapping an enumeration based on the raw result data, rather than using to_node_enumeration.

solnic commented 9 years ago

Maybe you could do the row_proc trick like in yaml adapter? OTOH it's nice to avoid intermediate objects so if we can make things work with those structs then it's better than coercing to hashes.

maetl commented 9 years ago

Yeah, my goal is definitely to avoid intermediate objects.

I was thinking of trying something like the row_proc. I’ve also been looking at the raw result data and it’s actually reasonably straightforward to return an enumerator directly from that, which would bypass most of the core monkeypatching.

The thing to bear in mind with the above examples is that the rels / CypherRelationship objects are really just resource link URIs, so they won’t actually have any hash/struct data unless it’s explicitly aliased in the query return. The mapping/representation problem doesn’t actually go away by removing the monkeypatching.

Arguably, only data explicitly declared in the query itself should be exposed by the dataset.