Search code examples
ruby-on-railssti

Rails STI mysql queries not using the "type" column


I have the following models:

class Mark < ActiveRecord::Base
  validates_presence_of :user
  validates_presence_of :page

  belongs_to :user

  has_many :mettings
  has_many :tags,   :through => :mettings
  has_many :terms,  :through => :mettings
end


class Metting < ActiveRecord::Base
  belongs_to :mark
  belongs_to :user

  belongs_to :tags,  :foreign_key => :metum_id, :class_name => "Metum"
  belongs_to :terms, :foreign_key => :metum_id, :class_name => "Metum"
end


class Metum < ActiveRecord::Base
  validates_presence_of   :type
  validates_presence_of   :name

  has_many    :mettings
  has_many    :marks, :through => :mettings

end


class Tag < Metum

end

class Term < Metum

end

And the issue is that when I look for the "tags" or "terms" of a Mark or a Metting, I get all of the "tags" and "terms" for that Mark or Metting. For example:

>> met = Metting.find(9)
  Metting Load (0.3ms)  SELECT `mettings`.* FROM `mettings` WHERE `mettings`.`id` = 9 LIMIT 1
=> #<Metting id: 9, mark_id: 1, metum_id: 1, user_id: 1, created_at: "2011-10-31 10:53:01", updated_at: "2011-10-31 10:53:01">
>> met.tags
  Metum Load (0.3ms)  SELECT `meta`.* FROM `meta` WHERE `meta`.`id` = 1 LIMIT 1
=> #<Term id: 1, type: "Term", name: "Authority", created_at: "2011-10-30 22:32:35", updated_at: "2011-10-30 22:32:35">
>> met.terms
  Metum Load (0.3ms)  SELECT `meta`.* FROM `meta` WHERE `meta`.`id` = 1 LIMIT 1
=> #<Term id: 1, type: "Term", name: "Authority", created_at: "2011-10-30 22:32:35", updated_at: "2011-10-30 22:32:35">

In this case, the Metting has only one term associated with it and not tags. The rails-generated queries are not making use of the "type" column in "Metum" in order to distinguish between Tags and Terms. Any ideas how I can fix this so that only tags and terms are returned in the above calls?

thanks.


Solution

  • You need to set the types properly in your :class_name attributes. To wit:

    belongs_to :tags,  :foreign_key => :metum_id, :class_name => "Tag"
    belongs_to :terms, :foreign_key => :metum_id, :class_name => "Term"
    

    else AR won't know how to resolve on the STI sub-type and will perform a lookup on the base class.