I'm working on an existing app which has the structure (simplified and) described below. One of our new queries is to find all activity in a company which is rather complicated and non-performant to build. It seems hard to write the query in ActiveRecord, so, I'm trying to use Scenic and build a Materialized View since this query is going to be mostly read-only.
So, we have Person
, Group
, Project
, Report
, Update
and ActivityReceipt
along with some join models. A person belongs to various groups and various projects.
My goal is to get show a feed of group activity of all of groups that a member is part of, so I'm looking to performantly fetch Activity
by group
, along with the author
information, sorted by time and it seems like a materialized view with the following columns would make that happen:
activity_receipt_id, group_id, person_id
class Person < ApplicationRecord
has_many :groups
has_many :projects
end
class Membership < ApplicationRecord
# id, group_id, person_id
belongs_to :group
belongs_to :person
end
class Company < ApplicationRecord
has_many :projects
has_many :people
end
class GroupDonation < ApplicationRecord
# id, group_id, project_id
belongs_to :group
belongs_to :project_id
end
class Project < ApplicationRecord
has_many :group_donations
has_many :people
end
class ActivityReceipt < ApplicationRecord
# polymorphic belongs_to relation to 'postable' which are reports, & updates
# so, it has id, postable_id, and postable_type as columns and then other specific metadata
belongs_to :postable
end
class Report < ApplicationRecord
# project_id, membership_id and other specific metadata
belongs_to :project
belongs_to :membership #to track the author
has_one :activity_receipt
end
class Update < ApplicationRecord
# project_id, membership_id and other specific metadata
belongs_to :project
belongs_to :membership #to track the author
has_one :activity_receipt
end
Conceptually, the query is for all the given group_ids
, fetch the associated projects and then their associated reports & updates, and then their activity receipts which is eventually needed. I'm not very familiar with writing SQL to generate a view so I have been struggling on how to make such a materialized view with polymorphic relations, and if it is even possible / recommended
Here is what I have so far:
SELECT groups.id AS group_id, people.id AS people_id, activity_receipts.id as activity_receipt_id
FROM groups
JOIN group_donations ON group_donations.group_id = groups.id
JOIN projects ON projects.id = group_donations.group_id
JOIN reports ON reports.project_id = project.id
JOIN updates ON updates.project_id = project.id
JOIN activity_receipts ON
// Stuck here