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

Possible AR Polymorphic Association Regression (5.2.0.beta2)? #31328

Closed
afair opened this Issue Dec 4, 2017 · 6 comments

Comments

Projects
None yet
5 participants
@afair
Contributor

afair commented Dec 4, 2017

Steps to reproduce

I have reduced the models in my application to the essential association. Post (parent) has a Tracker (polymorphic child association. Given a child, I need to get it's parent record.

class Post < ActiveRecord::Base
  # Note that Post uses an UUID id.
  has_one    :tracker, as: :track
end

class Tracker < ActiveRecord::Base
  # attributes include track_type (varchar) and track_id (uuid)
  belongs_to :track, polymorphic:true
end

In the context of the Bug Report Template My Template Source,
the association works as expected for the simplified case (not full application).
I have been trying to identify a failing case for it unsuccessfully.

Expected behavior

In Rails 5.1.4, this works (finding a parent from a polymorphic child):

>  Tracker.find(31).track
=> #<Post:0x00007ffbf38531c0
     id: "a85c5f88-6fca-473a-bdc0-205002907972", ... >

Actual behavior

After upgrading to Rails 5.0.2.beta2 (as well as on edge), I now get an exception:

>  t=Tracker.find(31)
=> #<Tracker:0x00007fd2eaca8360
     id: 31,
     track_type: "Post",
     track_id: "a85c5f88-6fca-473a-bdc0-205002907972", ... >

>  Tracker.find(31).track
ActiveRecord::InverseOfAssociationNotFoundError: Could not find the inverse association for track (nil in Post)
from /Users/allen/.rvm/gems/ruby-2.4.2/bundler/gems/rails-c383c4142a1c/activerecord/lib/active_record/reflection.rb:527:in `polymorphic_inverse_of'

Though I can get the association starting from the final point: Parent -> Child -> Parent

>  Post.find(t.track_id)
=> #<Post:0x00007fd2ebaa3668
    id: "a85c5f88-6fca-473a-bdc0-205002907972", ... >
>  Post.find(t.track_id).tracker
=> #<Tracker:0x00007fd2eb99b3d8
     id: 31,
     track_type: "Post",
     track_id: "a85c5f88-6fca-473a-bdc0-205002907972", ... >
>  Post.find(t.track_id).tracker.track
=> #<Post:0x00007fd2ec22a328
     id: "a85c5f88-6fca-473a-bdc0-205002907972", ... >

Digging into active_record/reflection.rb for 5.1.4, I see has_inverse? returns false, because
can_find_invserse_of_automatically? returns false.

def polymorphic_inverse_of(associated_class)
  #           can_find_inverse_of_automatically?(self) #=> false
  if has_inverse? #=> false
    #...
  end
end

While in 5.2.0.beta2, has_inverse? now returns :tracker and tries to get the inverse_relationship.
Since inverse_of "Does not work in combination with the :polymorphic options." (api docs) this fails,
and raises the Exception. It seems can_find_inverse_of_automatically? now returns true which it shouldn't. The documentation block says "Third, we must not have options such as :polymorphic ..." which this is.

def polymorphic_inverse_of(associated_class)
  #                can_find_inverse_of_automatically?(self) #=> true
  if has_inverse?  #=> :tracker
    #              associated_class #=> Post()
    #              options          #=> {:polymorphic=>true}
    if inverse_relationship = associated_class._reflect_on_association(options[:inverse_of]) #=> nil
      inverse_relationship
    else
      raise InverseOfAssociationNotFoundError.new(self, associated_class)
    end
  end
end

System configuration

Rails version: Rails 5.2.0.beta2 (and edge)

Ruby version: Ruby MRI 2.4.2

Thank you for your time! I appreciate all you do for the project!

@tradeli

This comment has been minimized.

Show comment
Hide comment
@tradeli

tradeli Dec 5, 2017

Maybe related #31338

tradeli commented Dec 5, 2017

Maybe related #31338

@fatkodima

This comment has been minimized.

Show comment
Hide comment
@fatkodima

fatkodima Dec 27, 2017

Contributor

Can't reproduce on 5.2.0.beta2 (and edge). All is working as expected.
My (assembled from yours pieces) test:

  def test_association_stuff
    post = Post.create
    Tracker.create(track:post)
    tracker = Tracker.first
    p tracker
    post = tracker.track
    p post

    assert_equal tracker.track_id, post.id

    t = Tracker.find(1)
    p Tracker.find(1).track
    p Post.find(t.track_id)
    p Post.find(t.track_id).tracker
    p Post.find(t.track_id).tracker.track
  end
Contributor

fatkodima commented Dec 27, 2017

Can't reproduce on 5.2.0.beta2 (and edge). All is working as expected.
My (assembled from yours pieces) test:

  def test_association_stuff
    post = Post.create
    Tracker.create(track:post)
    tracker = Tracker.first
    p tracker
    post = tracker.track
    p post

    assert_equal tracker.track_id, post.id

    t = Tracker.find(1)
    p Tracker.find(1).track
    p Post.find(t.track_id)
    p Post.find(t.track_id).tracker
    p Post.find(t.track_id).tracker.track
  end
@tradeli

This comment has been minimized.

Show comment
Hide comment
@tradeli

tradeli Dec 31, 2017

So maybe Kamipo fixed it but forgot to close this hahaha
I think it was here: commit

tradeli commented Dec 31, 2017

So maybe Kamipo fixed it but forgot to close this hahaha
I think it was here: commit

@kamipo

This comment has been minimized.

Show comment
Hide comment
@kamipo

kamipo Jan 6, 2018

Member

Closing this since can't reproduce on 5.2.0.beta2 (and edge, and all stable branches).

Member

kamipo commented Jan 6, 2018

Closing this since can't reproduce on 5.2.0.beta2 (and edge, and all stable branches).

@kamipo kamipo closed this Jan 6, 2018

@koenpunt

This comment has been minimized.

Show comment
Hide comment
@koenpunt

koenpunt Jan 8, 2018

Contributor

I actually am experiencing this issue with Rails 5.2.0.beta2..

Contributor

koenpunt commented Jan 8, 2018

I actually am experiencing this issue with Rails 5.2.0.beta2..

@koenpunt

This comment has been minimized.

Show comment
Hide comment
@koenpunt

koenpunt Jan 8, 2018

Contributor

Explicitly adding inverse_of: ... to my belongs_to ..., polymorphic: true, makes it work again tho..

Contributor

koenpunt commented Jan 8, 2018

Explicitly adding inverse_of: ... to my belongs_to ..., polymorphic: true, makes it work again tho..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment