Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node must be of the association's class when model is specified? #717

Closed
arikan opened this issue Mar 12, 2015 · 27 comments
Closed

Node must be of the association's class when model is specified? #717

arikan opened this issue Mar 12, 2015 · 27 comments

Comments

@arikan
Copy link

arikan commented Mar 12, 2015

While associating one model to another via the simplest declared connection, I've been getting the error below since we upgraded to Neo4j 2.2, Neo4jrb 4.1, Rails 4.2.

class User
  include Neo4j::ActiveNode
  has_one :out, :invitation

class Invitation
  include Neo4j::ActiveNode
  has_one :in, :sender, model_class: User, after: :decrement_sender_count
  has_one :out, :recipient, model_class: User   

@user = User.find(params[:id])
@invitation = Invitation.find_by(:token => params[:invitation][:token])
puts @invitation
@user.invitation = @invitation
ArgumentError - Node must be of the association's class when model is specified:

Invitation object is clearly there as puts #<Invitation:0x007ff1a9a1acc8>

The last line tries to make the association with the cypher below, then throws the error above.

Class#invitation#invitation 13ms MATCH (user18376:User), user18376-[rel1]->(result_invitation:Invitation) WHERE (ID(user18376) = {ID_user18376}) DELETE rel1 | {:ID_user18376=>18376}

This is weird: Class#invitation#invitation I don't get what's happening here? Any thoughts?

@subvertallchris
Copy link
Contributor

Try doing a bundle update on neo4j and neo4j-core if you haven't already,
there's been a lot of refactoring going on lately. Brian will probably have
a better idea than me but I'll check it out tomorrow, too, to see if I can
reproduce it.

On Wednesday, March 11, 2015, Burak Arikan notifications@github.com wrote:

While associating one model to another via the simplest declared
connection, I've been getting the error below since we upgraded to Neo4j
2.2, Neo4jrb 4.1, Rails 4.2.

class User
include Neo4j::ActiveNode
has_one :out, :invitation
class Invitation
include Neo4j::ActiveNode
has_one :in, :sender, model_class: User, after: :decrement_sender_count
has_one :out, :recipient, model_class: User
@user = User.find(params[:id])@invitation = Invitation.find_by(:token => params[:invitation][:token])
puts @invitation@user.invitation = @invitation

ArgumentError - Node must be of the association's class when model is specified:

Invitation object is clearly there as puts #Invitation:0x007ff1a9a1acc8

The last line tries to make the association with the cypher below:

Class#invitation#invitation 13ms MATCH (user18376:User),
user18376-[rel1]->(result_invitation:Invitation) WHERE (ID(user18376) =
{ID_user18376}) DELETE rel1 | {:ID_user18376=>18376}

This is wierd: Class#invitation#invitation

I don't get what's happening here?


Reply to this email directly or view it on GitHub
#717.

@arikan
Copy link
Author

arikan commented Mar 12, 2015

Thanks, just attempted to do an update, already have the latest.

Using neo4j-core 4.0.1 from https://github.com/neo4jrb/neo4j-core (at master)
Using neo4j 4.1.2 from https://github.com/neo4jrb/neo4j (at master)

Currently looking into it, let you know if I find more hints.

@arikan
Copy link
Author

arikan commented Mar 12, 2015

Trying to debug this problem, but no chance. One thing clear however, that, the error is caused by the change in the declared relation naming with Neo4jrb 4.1.

I tried the "legacy" as well as the new relation naming scheme, it both throws the same error.

config.neo4j.transform_rel_type = :legacy
ArgumentError - Node must be of the association's class when model is specified:

One interesting case: If I restart the server, it works for the first time, then keeps throwing the error above for the rest of the attempts.

@subvertallchris
Copy link
Contributor

What version were you using before? The change has an impact on relationship types but not the logic that determines whether a node is of the appropriate class to create the relationship.

@arikan
Copy link
Author

arikan commented Mar 12, 2015

We upgraded to version 4.1 from version 3.x.

As mentioned above, the invitation instance of the Invitation Model to associate (user.invitation = invitation) is clearly there, but it throws this "not appropriate" error, except when I restart the server, exact same association code works for the first time, and stops working in the following attempts... which is really weird.

@arikan
Copy link
Author

arikan commented Mar 12, 2015

So, I ended up creating the declared relation like an undeclared relation, which worked fine:

@user.create_rel('#received_invitation', @invitation)

However, the problem with association below remains:

@user.received_invitation = @invitation
# ArgumentError - Node must be of the association's class when model is specified:

Also note that I use config.neo4j.transform_rel_type = :legacy

@subvertallchris
Copy link
Contributor

If you successfully create the relationship, does @user.received_invitation return nodes as expected?

@arikan
Copy link
Author

arikan commented Mar 12, 2015

Yes @user.received_invitation works fine

@arikan
Copy link
Author

arikan commented Mar 20, 2015

This error Node must be of the association's class is still unresolved.

However, using a relation name different than the associating model and referencing with origin: like below works:

class User
  has_many :out, :sent_invitations, model_class: Invitation
  has_one :out, :received_invitation, model_class: Invitation

class Invitation
  has_one :in, :sender, model_class: User, origin: :sent_invitations
  has_one :in, :recipient, model_class: User, origin: :received_invitation 

# these work without errors
@invitation.sender = current_user # or current_user.sent_invitations << @invitation
@user.received_invitation = @invitation # or @invitation.recipient = @user

But, if I use the model name for relation and do not use origin:, it throws error (this used to work in neo4jrb v3.x):

class User
    has_many :out, :invitations

class Invitation
   has_one :in, :sender, model_class: User

current_user.invitations << @invitation
# ArgumentError - Node must be of the association's class when model is specified:

@arikan
Copy link
Author

arikan commented Mar 20, 2015

Well, it turns out the source of the problem is the find method in Neo4jrb 4.

While creating a relation, there is a check of both model classes here:
https://github.com/neo4jrb/neo4j/blob/master/lib/neo4j/active_node/query/query_proxy.rb#L170

And, somehow the find method returns an unknown class, altough it is a correct model.

hub = Hub.find(params[:hub_id])

if hub.is_a?(Hub)
  puts "correct type";  puts hub
else
  puts "wrong type??"; puts hub
end

# returns:
# wrong type??? 
# #<Hub:0x007fcfcee56f50>

# thus, this throws error: Node must be of the association's class
hub.nodes << @node

Whereas if I do this, it works fine:

hub = Hub.first

if hub.is_a?(Hub)
  puts "correct type";  puts hub
else
  puts "wrong type??"; puts hub
end

# returns:
# correct type 
# #<Hub:0x007f8b018bd3f8>

# it works fine here: 
hub.nodes << @node

Can you take a look at what's wrong with the find method?

@subvertallchris
Copy link
Contributor

I can't seem to reproduce this. Just added one more test:

bba38ce

That passes when I run it. When I test it in my sample app, everything checks out, too.

Loading development environment (Rails 4.1.7)
2.2.0 :001 > s = Student.create
 => #<Student age: nil, created_at: 1426895352, gpa: nil, hair_color: nil, important_date: nil, important_time: nil, key: nil, links: nil, name: nil, new_prop: nil, normalized_name: nil, occupation: nil, omgrange: nil, test_scores: nil, updated_at: 1426895352> 
2.2.0 :002 > s.id
 => "89d6fb4c-7073-4d1d-8a63-77705fd5a9fa" 
2.2.0 :003 > w = Student.find("89d6fb4c-7073-4d1d-8a63-77705fd5a9fa")
 CYPHER 15ms MATCH (result_student:`Student`) WHERE (result_student.uuid = {result_student_uuid}) RETURN result_student ORDER BY ID(result_student) LIMIT {limit_1} | {:result_student_uuid=>"89d6fb4c-7073-4d1d-8a63-77705fd5a9fa", "limit_1"=>1}
 => #<Student age: nil, created_at: 1426895352, gpa: nil, hair_color: nil, important_date: nil, important_time: nil, key: nil, links: nil, name: nil, new_prop: nil, normalized_name: nil, occupation: nil, omgrange: nil, test_scores: nil, updated_at: 1426895352> 
2.2.0 :004 > w.is_a?(Student)
 => true 

Can you share the full Hub model?

@arikan
Copy link
Author

arikan commented Mar 21, 2015

hmm if I try in the console it works fine too.

But this happens in the controller context, why would it make any difference?

(I am on rails 4.2, not that it makes a difference, jusy fyi.)

@subvertallchris
Copy link
Contributor

I can't think of any reason. Is it possible that your query is returning nil?

@arikan
Copy link
Author

arikan commented Mar 21, 2015

Nope, the query returns the object, as it prints it in the console, altough it is the wrong type:

if hub.is_a?(Hub)
  puts "correct type";  puts hub
else
  puts "wrong type??"; puts hub
end

# returns:
# wrong type??? 
# #<Hub:0x007fcfcee56f50>

@subvertallchris
Copy link
Contributor

What does puts hub.inspect show?

@arikan
Copy link
Author

arikan commented Mar 21, 2015

hub = Hub.find(params[:hub])

if hub.is_a?(Hub)
  puts "correct type"; puts hub
else
  puts "wrong type???"; puts hub
end

puts hub.inspect

# returns: 
# wrong type???
# #<Hub:0x007ffe63afd188>
# #<Hub created_at: Tue, 17 Mar 2015 04:42:25 +0000, description: ""...

@arikan
Copy link
Author

arikan commented Mar 21, 2015

So if I restart the server, is_a? check starts returning "correct type", but after a few calls, it starts returning "wrong type" again... really confusing, what could make this difference?

@subvertallchris
Copy link
Contributor

Really weird. I can't think of what would do that. What does puts hub.class show?

@arikan
Copy link
Author

arikan commented Mar 21, 2015

same thing:

...
puts hub.class
puts hub.class.name

returns:
# wrong type???
# #<Hub:0x007f8218a10e40>
# Hub
# Hub

@subvertallchris
Copy link
Contributor

If it works for a while and stops, my feeling is that another model or class is being loaded at some point that's redefining a method used by the gem. Any chance you can look for something like this?

@arikan
Copy link
Author

arikan commented Mar 21, 2015

Would that be the Devise gem? Almost all our model's controllers have the authentication.

before_filter :authenticate_user!

@subvertallchris
Copy link
Contributor

I doubt it, Devise is pretty popular and we've never had this reported. If you do hub.method(:is_a?).source_location what do you get? I doubt that'll work.

@arikan
Copy link
Author

arikan commented Mar 22, 2015

I tried puts hub.method(:is_a?).source_location it does not print anything... in both situations while hub.is_a?(Hub) returning true and false.

@ivopatty
Copy link

ivopatty commented Jun 3, 2015

This still happens in the controller context in my application. It only appears to happen when a file is changed in the application. A restart of the rails server fixes the issues until a file is changed again.

When accessing the console from a webview in Rails 4.2 Model.find(Model.first.uuid).is_a?(Model) returns false, while running in in rails c returns true

@djvs
Copy link

djvs commented Jun 18, 2015

Same bug I had today. Also using Devise btw, but temporarily commenting out before_filter :authenticate_user! does not change anything. Same thing, it will start cropping up again after a few calls.

My unsubstantiated hunch - there's some kind of global logic being used somewhere in the gem, that will overwrite the global used after .find(...) if another one is called, and then some features will stop working? Shrug

@subvertallchris
Copy link
Contributor

This is fixed in 5.2.x.

@subvertallchris
Copy link
Contributor

Thanks for everyone's help and patience with troubleshooting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants