Neo4J gem associations and creating relationships

468 views Asked by At

This goes back to my issue with this Neo4J Gem - Saving undeclared relationships

In the documentation, they give an example of this

post.comments = [comment1, comment2]  # Removes all existing relationships
post.comments << comment3             # Creates new relationship

From what I understand, the first line would remove all relationships because it's manually setting all the associated comments to be comment1, comment2.

But what does line 2 do? post.comments should be retrieving the comments associated with post. Thus it seems to be creating a relationship with comment3 and the other comments. But don't we want to create a relationship between Posts and comments?

Either I'm not understanding the syntax and what it's doing or what is written isn't clear what is happening.

Looking at my example, we have

def create
    @event_question = EventQuestion.new(event_question_params)
    if @event_question.save
        event = Event.find(params[:event_id])
        @event_question.update(admin: current_user.facebook_id)
        @event_question.events << event
        redirect_to @event
    else
        redirect_to :back
    end
end

If event is my event node and @event_question is my event_question node, why does @event_question.events << event create the relationship between my event_question and event?

Right now I'm getting an undefined method '<<' for nil:NilClass in my controller which is a another problem altogether.

My event.rb has

  has_many :in, :event_questions, type: 'questions_of'

and my event_question.rb has

  has_one :out, :events, origin: :event_questions

@event_question and event both exist but @event_question.events will return nil

1

There are 1 answers

0
subvertallchris On BEST ANSWER

post.comments << comment3 creates an additional relationship between post and comment3. It doesn't do anything with the other relationships.

The reason this looks weird to you is because post.comments doesn't retrieve anything from the database. Call class on it or any has_many association and you'll see that it's a Neo4j::ActiveNode::Query::QueryProxy object, which you can think of as an unexecuted query. It doesn't actually go out and touch the database until you call an enumerable method like first or each OR a custom operator like = or <<. << is defined in query_proxy.rb.

The lazy evaluation of QueryProxy objects is why you're able chain methods and do things like post.comments.liked_by.username. It waits until it's clear that you need something from the database before hitting it.

The reason you're getting undefined method '<<' for nil:NilClass is because has_one relationships work differently. They are not executed lazily because there's nothing to filter, there's nothing to chain, there's only one possible result. As soon as you call @event_question.events, it hits the database and since nothing is set, it returns nil. The error means what it says: nil does not have a << method. Use @event_question.events = event and you'll be fine. You may want to change that association to has_one :out, :event, origin: :event_questions to avoid confusion in the future.