ActiveRecord将两个关系的范围命名为一个模型

时间:2012-12-05 21:24:30

标签: ruby-on-rails ruby activerecord scope named-scope

我正在使用两种不同模型的多态关联到标记模型。很棒,很容易。但是,这两个模型中的一个也属于另一个模型。

class Facility < ActiveRecord::Base
  has_many :units
  has_many :taggings, :as => :taggable
  has_many :tags, :through => :taggings
end
class Unit < ActiveRecord::Base
  belongs_to :facility
  has_many :taggings, :as => :taggable
  has_many :tags, :through => :taggings
end
class Tagging < ActiveRecord::Base
  belongs_to :taggable, :polymorphic => true
  belongs_to :tag
end
class Tag < ActiveRecord::Base
  has_many :taggings
end

我正在尝试编写一个范围来检索某个标记的所有单位,包括那些属于具有该标记的工具的单位。这不起作用:

named_scope :by_tag_id, lambda {|tag_id| 
{ 
  :select => "DISTINCT units.*",
  :joins => [:taggings, {:facility => :taggings}],
  :conditions => ["taggings.tag_id = ? OR taggings_facilities.tag_id = ?", 
    tag_id.to_i, tag_id.to_i] 
}}

对于那个named_scope,我只获得那些带有标记的单位。

有什么想法?我错过了一些明显的东西吗?

更新

不幸的是,我在Rails 2.3.x,Ruby 1.8.7上。

我正在尝试使用更明确编写的连接的一些技术。

更新2

我无法回答我自己的问题,因为我没有声誉。哎呀。我真的应该贡献更多......

嗯,我想我只需要戳一下,再推一点。这就是我的工作:

named_scope :by_tag_id, lambda {|tag_id| 
  { 
    :select => "DISTINCT units.*",
    :joins => [
        "INNER JOIN facilities as bti_facilities ON units.facility_id = bti_facilities.id",
        "LEFT JOIN taggings AS bti_facilities_taggings 
          ON bti_facilities_taggings.taggable_id = bti_facilities.id AND bti_facilities_taggings.taggable_type = 'Facility'",
        "LEFT JOIN taggings AS bti_units_taggings ON bti_units_taggings.taggable_id = units.id AND bti_units_taggings.taggable_type = 'Unit'",
      ],
    :conditions => ["bti_units_taggings.tag_id = ? OR bti_facilities_taggings.tag_id = ?", tag_id.to_i, tag_id.to_i] 
  }
}

我正在使用一些有意混淆的表别名,以便尽量避免与其他命名范围发生冲突。 (我没有设备别名启动,我在查询中遇到SQL错误,我试图链接另一个引用设施表的范围。)

如果有人有更好的答案或对我的方法有一些反馈,我会来听取它。

2 个答案:

答案 0 :(得分:0)

我发现您已经回答了问题,但如果您在原始查询中使用:include =>而不是:join =>,则会生成LEFT OUTER JOIN。也就是说,您可能不需要急切加载关联,只需查询它,因此您的里程可能会有所不同。

答案 1 :(得分:0)

我想知道你能不能写出这样的东西?

named_scope :by_tag_id, lambda {|tag_id| 
  { 
    :select     => "DISTINCT units.*",
    :include    => [:tags, {:facility => :taggings}],
    :conditions => { :tags => { :tag_id => tag_id } }
  }
}