Combine STI and polymorphic with rails 4
Asked Answered
A

1

5

I'm running with some issues trying to combine STI and polymorphic associations with the following structure :

class User < ActiveRecord::Base
end

class Runner < User
  has_many :subscriptions, as: :subscriber, :dependent => :destroy
  has_many :areas, through: :subscriptions
end

class Trainer < Runner
end

class Subscription < ActiveRecord::Base
  belongs_to :subscriber, polymorphic: true
  belongs_to :area
end

class Area
end

When I try in the console :

Runner.find(2101).areas

SELECT "areas".* FROM "areas" INNER JOIN "subscriptions" ON "areas"."id" = 
"subscriptions"."area_id" WHERE "subscriptions"."subscriber_id" = $1 AND 
"subscriptions"."subscriber_type" = $2  [["subscriber_id", 2101], ["subscriber_type", 
"User"]]
 => #<ActiveRecord::Associations::CollectionProxy []> 

However there is a record with this runner :

 #<Subscription id: 3, area_id: 2, subscriber_id: 2101, subscriber_type: "Runner", primary_area: true>

But I don't understand why active record is looking for a User and not a Runner.

Any idea why ? or better design ?

Animalism answered 19/2, 2014 at 16:27 Comment(1)
Here is a very similar question with more answers: #9629110Avis
T
9

From rails documentation

Using polymorphic associations in combination with single table inheritance (STI) is a little tricky. In order for the associations to work as expected, ensure that you store the base model for the STI models in the type column of the polymorphic association. To continue with the asset example above, suppose there are guest posts and member posts that use the posts table for STI. In this case, there must be a type column in the posts table.

Change your subscription class like this

class Subscription < ActiveRecord::Base
  belongs_to :subscriber, polymorphic: true
  belongs_to :area

  def subscriber_type=(sType)
     super(sType.to_s.classify.constantize.base_class.to_s)
  end
end
Tumbrel answered 19/2, 2014 at 16:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.