has_many :through association through two different associations
I have four model classes:
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
I want to find all of the events for a particular group. I figure this is a has_many :through association, but how do I specify a has_many on Group that finds all events in the projects or personal_blogs of a group? I could, of course, sp开发者_运维知识库ecify two associations and concatenate the results, but then I have to re-sort, limit, condition, etc. in Ruby, which could potentially be a performance nightmare with many events. I'd like to do this within ActiveRecord to avoid such a nightmare.
You could define a method in the Group class like next:
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
If you don't like SQL like the previous one, it's always possible to use Single Table Inheritance. This solution depends on your classes attributes and behavior, but will allow you to use a "has_many through" association.
Why not just do:
class Group < ActiveRecord::Base
has_many :projects
has_many :personal_blogs
def all_events
projects.events + personal_blogs.events
end
end
If you need an association that you can preload you could specify a custom 'from' query that includes the group id with the event.
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
精彩评论