Rails STI mysql查询不使用“类型”列

时间:2011-10-31 17:23:11

标签: ruby-on-rails sti

我有以下型号:

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

问题在于,当我查找Mark或Metting的“标签”或“术语”时,我会获得该Mark的所有“标签”“条款”或默坦。例如:

>> 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">

在这种情况下,Metting只有一个与之关联的术语而不是标签。 rails生成的查询未使用“Metum”中的“type”列来区分Tags和Terms。我有什么想法可以解决这个问题,以便只在上面的调用中返回标签和术语吗?

感谢。

2 个答案:

答案 0 :(得分:2)

您需要在:class_name属性中正确设置类型。即:

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

否则AR将不知道如何解析STI子类型并将在基类上执行查找。

答案 1 :(得分:1)

您可以为您的关系添加条件,如下所示:

belongs_to :tags,
           :foreign_key => :metum_id,
           :class_name => "Metum",
           :conditions => ['type = ?', 'Tag']

belongs_to :terms,
           :foreign_key => :metum_id,
           :class_name => "Metum",
           :conditions => ['type = ?', 'Term']