#92 ✓resolved
Peter Ferne

has_one...from using the wrong has_n...to

Reported by Peter Ferne | November 23rd, 2009 @ 04:13 PM | in 0.4.0

I have two models (Person and Subject) with has_n relationships (with the same name :interests) to a third model (Interest). The Interest model has two corresponding has_one relationships (:person and :subject).

Browsing in the neo-shell I see this:

neo-sh (0)$ ls 2
*classname =[Person]
*name      =[Pythia]
(me) --<interests>--> (4, Interest)
neo-sh (0)$ ls 3
*classname =[Subject]
*name      =[Persia]
(me) --<interests>--> (4, Interest)
neo-sh (0)$ ls 4
*classname =[Interest]
(me) <--<interests>-- (3, Subject)
(me) <--<interests>-- (2, Person)

So far so good. interest.person returns the expected Person node BUT interest.subject returns the same Person node instead of the expected Subject node.

See http://pastie.org/private/z08tigpcni0ozreaxyyig

Comments and changes to this ticket

  • Andreas Ronge

    Andreas Ronge November 23rd, 2009 @ 04:46 PM

    • State changed from “new” to “open”
    • Milestone set to 0.3.3

    This is because Interests has two incoming relationships with the same name: interests.
    Maybe the method should throw an exception if one tries to use two has_one relationship with the same relationship id.
    So this not a bug, but I think an raising an exception would help. Would do you think ?

  • Peter Ferne

    Peter Ferne November 23rd, 2009 @ 05:08 PM

    I think that if it's not allowed then it probably should raise an exception as you suggest, and perhaps it would be good to update the README too.

    As I was thinking of it in terms of defining a method interests on each of those two classes (Person and Subject) it certainly wasn't clear to me that it would give rise to a conflict. Ideally it wouldn't, IMHO.

    Would the same problem occur if I added a different class to each of the two interests relationships? Is this just a fundamental limitation of has_one?

  • Andreas Ronge

    Andreas Ronge November 23rd, 2009 @ 07:40 PM

    The only difference between has_n and has_one is that the has_one method defines a = method which under the hood uses the << operator.
    The problem is that there are two incoming relationship with the same name, e.g.

    A ----> B <------ C

    If there are two incoming relationship with the same name then there is no way to distinguish which one is which (except by traversing/following the relationship).
    To avoid this conflict we have to generate unique relationship name for relationships defined with a from and to method (or maybe all has_n and has_one methods)

    class Foo
    has_one(:bar_item).from(Bar) # uses .from so generate unique relationship name has_one(:baaz_item).from(Baaz) end

    class Bar
    has_n(:items).to(Foo) end

    class Baaz
    has_n(:items).to(Foo) end

    would create relationships

    Baar ---<bar_items>--> Foo <----<baaz_items> --- Baaz

    Have to do some more thinking about this if this is a good idea or not ...

  • Peter Ferne

    Peter Ferne November 23rd, 2009 @ 08:02 PM

    Yes, I think that is more or less what I assumed was happening under the covers. I appreciate it's something that needs some thought though. I'll try to take a look at the relevant code too and see if anything occurs to me.

  • Peter Ferne

    Peter Ferne November 24th, 2009 @ 12:57 PM

    I seem to have solved my immediate problem by simply dropping the method names from the from clause:

    class Interest
      has_one(:person).from(Person) #, :interests)
      has_one(:subject).from(Subject) #, :interests)

    but this makes me wonder if there may be an issue with relationships being created twice - both by the has_n...to... and the has_one...from.... Presumably has_n and has_one ought to check for preexisting relationships before creating a new one.

  • Andreas Ronge

    Andreas Ronge November 24th, 2009 @ 08:38 PM

    I think it will not work from both directions.

    I guess that it will generate outgoing relationship
    person_node -- (person) --> interest_node subject_node -- (subject) --> interest_node

    when you do:
    interest_node.person = person_node interest_node.subject = subject_node

    And when you do
    person_node.interests << interest_node

    It will create the following relationships
    person_node -- (interests) -- > interest_node

    So if you add an interest on a person then you can not access it with the person accessor on the Interest node.

  • Peter Ferne

    Peter Ferne November 25th, 2009 @ 06:37 PM

    Yes, you're right. I have reintroduced the from clauses and manually renamed the relationships to avoid clashes for now. I hope to revisit this later.

  • Andreas Ronge
  • Andreas Ronge

    Andreas Ronge December 1st, 2009 @ 08:57 PM

    • Milestone set to 0.4.0
  • Andreas Ronge
  • Andreas Ronge

    Andreas Ronge January 15th, 2010 @ 07:38 PM

    I think this issue is fixed. You can check if it solves your problem.

  • Andreas Ronge

    Andreas Ronge January 22nd, 2010 @ 03:49 PM

    • State changed from “open” to “resolved”

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

Neo4j.rb is a graph database framework for JRuby.

It provides:

* Mapping of ruby objects to nodes in networks rather than in tables.
* Storage of ruby object to a file system.
* Fast traversal of relationships between nodes in a hugh node space.
* Transaction with rollbacks support.
* Indexing and quering of ruby objects.
* Integration with Rails

People watching this ticket

Referenced by