has_many:通过两个不同的关联联系

时间:2010-02-26 19:22:39

标签: ruby-on-rails activerecord

我有四个模型类:

class Group < ActiveRecord::Base
  has_many :projects
  has_many :personal_blogs
end

class Project < ActiveRecord::Base
  has_many :events, :as => :event_producer
end

class PersonalBlog < ActiveRecord::Base
  has_many :events, :as => :event_producer
end

class Event < ActiveRecord::Base
  belongs_to :event_producer, :polymorphic => true
end

我想找到特定群组的所有活动。我认为这是一个has_many:通过关联,但是如何在Group上指定has_many来查找项目的个人事件中的所有事件?当然,我可以指定两个关联并连接结果,但是我必须在Ruby中重新排序,限制,条件等,这可能是许多事件的性能噩梦。我想在ActiveRecord中做到这一点,以避免这样的噩梦。

3 个答案:

答案 0 :(得分:5)

您可以在Group类中定义一个方法,如下一个:

class Group < ActiveRecord::Base
  has_many :projects
  has_many :personal_blogs

  def events
    Event.find(:all, :conditions => ['(type = ? AND event_producer_id IN (?)) OR (type = ? AND event_producer IN (?))', 'project', project_ids, 'personal_blog', personal_blog_ids])
  end
end

如果你不像前一个那样喜欢SQL,那么总是可以使用单表继承。此解决方案取决于您的classes attributes and behavior,但允许您使用“has_many through”关联。

答案 1 :(得分:0)

为什么不这样做:

class Group < ActiveRecord::Base
  has_many :projects
  has_many :personal_blogs

  def all_events
    projects.events + personal_blogs.events
  end
end

答案 2 :(得分:0)

如果您需要可以预加载的关联,则可以指定一个自定义“发件人”查询,其中包括带有事件的组ID。

class Group < ActiveRecord::Base
  has_many :projects
  has_many :personal_blogs
  has_many :events, -> {from(<<~SQL)}
    (
      SELECT DISTINCT e.*, g.id as group_id
      FROM events e
        LEFT JOIN projects p ON p.event_id = e.id
        LEFT JOIN personal_blogs pb ON pb.event_id = e.id
        INNER JOIN groups g ON g.id IN (p.group_id, pb.group_id)
    ) as events
  SQL
end