Andy Harvey
Andy Harvey

Reputation: 12663

How to form a polymorphic has_many on an inherited class

In a Rails 4.2 app I have a model that inherits from Draftsman.

module ActsAs
  class Draft < Draftsman::Draft
    include ActsAs::Votable
  end
end 

Users can vote to approve/reject edits, and the ActsAs::Votable mixin adds this polymorphic association and methods.

module ActsAs
  module Votable
    extend ActiveSupport::Concern
    included do
      has_many :votes_for, 
        class_name: 'ActsAs::Vote',
        as: :votable, 
        dependent: :destroy
    end
  end
end

This works fine for most parent models, but I am having trouble with this inherited Draftsman class.

I can create a vote

ActsAs::Vote.last
=> #<ActsAs::Vote id: 10, votable_id: 6, votable_type: "Draftsman::Draft">

but I am unable to return a draft's votes

@draft = ActsAs::Draft.find(6)
@draft.votes_for
=> #<ActiveRecord::Associations::CollectionProxy []>

I have tried modifying the vote creation method to set votable_type as ActsAs::Draft rather than the inherited Draftsman::Draft, but the same problem persists.

ActsAs::Vote.last
=> #<ActsAs::Vote id: 10, votable_id: 6, votable_type: "ActsAs::Draft">
@draft = ActsAs::Draft.find(6)
@draft.votes_for
=> #<ActiveRecord::Associations::CollectionProxy []>

The relationship is obviously not defined on Draftsmans::Draft

@draft = Draftsman::Draft.find(6)
@draft.votes_for
NoMethodError: undefined method `votes_for' for #<Draftsman::Draft:0x007fd7e6de9660>

Why am I unable to fetch the child votes via @draft, when ActsAs::Vote.all shows that the records exist in the table?

Upvotes: 2

Views: 381

Answers (1)

Anthony E
Anthony E

Reputation: 11245

This is a known issue when using polymorphic associations with STI.

See: Why polymorphic association doesn't work for STI if type column of the polymorphic association doesn't point to the base model of STI?

Personally, I'm dealing with this issue myself by using the store_base_sti_class (gem: https://github.com/appfolio/store_base_sti_class), which patches the STI behavior with Rails.

Upvotes: 1

Related Questions