Source Reflection Errors with has_many :through

2019-05-04 20:31发布

问题:

I'm attempting to create a system where my site's users can favorites pages. Those pages have two types, either clubs or sports. So, I have four models, associated as such:

User Model:

class User < ActiveRecord::Base
    ..
    has_many :favorites
    has_many :sports,    :through => :favorites
    has_many :clubs,     :through => :favorites
    ..
end

Favorites Model:

class Favorite < ActiveRecord::Base
    ..

    belongs_to :user
    belongs_to :favoritable, :polymorphic => true

end

Club Model:

class Club < ActiveRecord::Base
    ..

    has_many :favorites, :as => :favoritable
    has_many :users, :through => :favorites

    def to_param
      slug
    end
end

Sport Model:

class Sport < ActiveRecord::Base
    ..

    def to_param
        slug
    end

    ..

    has_many :favorites,   :as => :favoritable
    has_many :users,       :through => :favorites

    ..
end

Essentially, the User has_many sports or clubs through favorites, and the association between favorites, sports, and clubs is polymorphic.

In practice, this is all working exactly the way I want it to, and the whole system I have designed works. However, I'm using Rails_Admin on my site, and I get an error in three places:

  1. When loading the Dashboard (/admin) the first time. If I refresh the page, it works fine.
  2. When loading the User model in Rails_Admin
  3. When loading the Favorites model in Rails_Admin

Here is the error message on /admin/user (gist). All of the errors are similar, referencing ActiveRecord::Reflection::ThroughReflection#foreign_key delegated to source_reflection.foreign_key, but source_reflection is nil:.

Can anyone point me in the right direction so that I can fix this? I've searched all over, and asked other programmers/professionals, but no one could spot the error in my models. Thanks so much!

回答1:

Alright, well, I finally worked this out, and figured that I'd post the fix just in case it helps someone else out in the future (no one likes finding someone else with the same problem and no posted answer).

As it turns out, with a polymorphic has_many :through, there is a little more configuration needed. My User model should have looked like this:

class User < ActiveRecord::Base
    ..
    has_many :favorites
    has_many :sports, :through => :favorites, :source => :favoritable, :source_type => "Sport"
    has_many :clubs,  :through => :favorites, :source => :favoritable, :source_type => "Club"
    ..
end

This answer to another question about polymorphic has_many :through associations is what helped me figure this out.



回答2:

I encountered this error when the code included a has_many for an association that doesn't exist (mid-refactor). So it can also be caused by some general has_many misconfigure. The Ruby/Rails code never cares because the dynamic style of Ruby means the association is only called on demand. But Rails-Admin exhaustively inspects properties, leading to reflection problems.