Neo4J Gem - Saving undeclared relationships

216 views Asked by At

I am trying to create a realtionship between two nodes as described here https://github.com/neo4jrb/neo4j/wiki/Neo4j-v3-Declared-Relationships from_node.create_rel("FRIENDS", to_node)

I am getting an undefined method for create_rel

What am I doing wrong? I am trying to create a Q+A system inside another model. So both Questions and Answers are treated as models right now.

I'm getting a undefined methodcreate_rel' for #

event.rb

  has_many :out, :event_questions

event_question.rb

  has_one :in, :events
  has_many :out, :event_answers

  def create_questions_of(from_node,to_node)
    from_node.create_rel("questions_of", to_node)
  end

event_answer.rb

  has_one :in, :event_questions

event_questions_controller.rb

def new
    #is this needed
end

def create
    @event_question = EventQuestion.new(event_question_params)
    if @event_question.save
        @event = Event.find(params[:id])
        @event_question.update(admin: current_user.facebook_id)
        @event_question.create_questions_of(self,@event)
        redirect_to @event
    else
        redirect_to @event
    end
end

private

    def event_question_params
        params.require(:event_question).permit(:question)
    end

I have my new question sitting inside the event's index page since I wanted to list all the questions on the event after. I don't even need a new method in my controller right? I also don't really know how I would obtain the event that my question form is sitting on. Is that accessible through params?

UPDATE

Did you mean this

  def create_questions_of(to_node)
    self.create_rel("questions_of", to_node)
  end

and

 @event_question.create_questions_of(@event)

So I think I need to change my routes as well and nest questions inside to create events/123/questions/

Then I can grab events_id and use find

UPDATE #2

events_controller.rb

def show
    @event = Event.find(params[:id])
    @event_question = EventQuestion.new
end

event.rb

  has_many :out, :event_questions, type: 'questions_of'

event_question.rb

  has_one :in, :events, origin: :event_questions

events/show.html.erb

<%= form_for [:event, @event_question] do |f| %>

#form stuff

<% end %>

event_questions_controller.rb

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

routes.rb

resources :events do
    resources :event_questions, only: [:create, :destroy]
  end
1

There are 1 answers

8
subvertallchris On BEST ANSWER

create_rel worked fine when I tested it just now. Is it saying undefined method 'create_rel' for nil:NilClass? If so, it means that your from_node variable doesn't actually have a node set. Make sure your objects are what you think they are.

The better question here: why do you want to do this? When you create an undeclared relationship, you have to write your own Cypher queries whenever you want to use it. If it's part of your code and you are using it regularly, it should probably have has_many associations in your models. create_rel really only exists to provide interoperability with nodes that don't have models.

As for your other question, you don't need a new action unless there's a route and a view that corresponds with it. If you're loading the form for a new question on your index page, that's fine. If your URL is something like http://127.0.0.1:3000/events/123/questions/, then you can get the Event ID in params[:event_id]. Run the rake routes command from your project's directory and it'll spit out lots of information that includes the parameter names.

Finally, when you use self in @event_question.create_questions_of(self,@event), you're going to get the controller. If you want it to refer to the @event_question, just remove that first argument from create_questions_of and use self from within the method.

Edit: Part 2

You're getting the undefined method because self in @event_question.create_questions_of(self,@event) is the controller. You're trying to send @event_question to itself, I think. Don't do that, just call self from within create_questions_of and you'll get current EventQuestion.

You use ActiveRel if you want callbacks, validations, properties, etc,... If you just want a simple relationships, just setup the has_many associations in each model, omit rel_class, and either set them both to the same type or set origin on one.

class Event
  include Neo4j::ActiveNode
  has_many :in, :event_questions, type: 'questions_of'
end

class EventQuestion
  include Neo4j::ActiveNode
  has_many :out, :events, origin: :event_questions
end

origin says, "Look for this association in the reciprocal model and use the type it defines." It lets you not have to worry about synchronizing the type between associations.

After that, you can do @event_question.events << @event and it'll create a new relationship for you.