This project is archived and is in readonly mode.

#2756 ✓stale
tsechingho

[patch] The polymorphic type field should be subclass name instead of base class name when using polymorphic association with single table inheritance

Reported by tsechingho | June 4th, 2009 @ 11:57 AM | in 3.x

For a long time it was a problem for people wanting to use polymorphic association with single table inheritance.
The solution was pointed out (ticket #547, http://dev.rubyonrails.org/ticket/6485, http://dev.rubyonrails.org/ticket/8841).

For example, we should use @owner.class.name.to_s rather than @owner.class.base_class.name.to_s for the record["#{@reflection.options[:as]}_type"] attribute in set_belongs_to_association_for method in active_record/associations/association_proxy.rb.
Beside that, we should consider the namespace problem (full class name or demodulized name) mentioned in ticket #465. So @owner.class.sti_name.to_s is more proper than @owner.class.name.to_s.

When we look at the whole active record library, this wrong taken causes many place should be fixed (association_preload.rb, associations.rb, association_proxy.rb, belongs_to_polymorphic_association.rb, has_many_association.rb, has_many_through_association.rb, has_one_association.rb and autosave_association.rb).

I prepared a patch to resolve these situations. This patch should also fix problems mentioned in ticket #2435, #2594, #2601.
The related test cases were fixed too (join_model_test.rb, eager_test.rb, eager_load_includes_full_sti_class_test.rb).
So there were no problems even if we have complicated models like 'Post', 'Tag' and 'Tagging' in test/models.

class Post < ActiveRecord::Base
  has_many :taggings, :as => :taggable

  has_many :tags, :through => :taggings
  has_many :funky_tags, :through => :taggings, :source => :tag
  has_many :super_tags, :through => :taggings

  has_one :tagging, :as => :taggable

  has_many :invalid_taggings, :as => :taggable, :class_name => "Tagging", :conditions => 'taggings.id < 0'
  has_many :invalid_tags, :through => :invalid_taggings, :source => :tag
end

class Tagging < ActiveRecord::Base
  belongs_to :tag, :include => :tagging
  belongs_to :super_tag,   :class_name => 'Tag', :foreign_key => 'super_tag_id'
  belongs_to :invalid_tag, :class_name => 'Tag', :foreign_key => 'tag_id'
  belongs_to :taggable, :polymorphic => true, :counter_cache => true
end

class Tag < ActiveRecord::Base
  has_many :taggings
  has_many :taggables, :through => :taggings
  has_one  :tagging

  has_many :tagged_posts, :through => :taggings, :source => :taggable, :source_type => 'Post'
end

The remain question is this patch will cause problems to plugins which also use 'base_class.name', like 'has_many_polymorphs' as I know.
Maybe more test cases should be added for this path, but I feel that this problem should be solved before rails 3.0.

Comments and changes to this ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Attachments

Referenced by

Pages