class CreateSnipStatsView < ActiveRecord::Migration[6.1]
def change
execute <<~SQL
CREATE VIEW snip_stats AS
SELECT s.id AS snip_id,
s.author_id,
s.views,
s.score,
COUNT(c.id) AS comments
FROM snips s
LEFT JOIN comments c ON c.post_type = 'Snip' AND c.post_id = s.id
GROUP BY s.id;
SQL
end
end
class SnipStat < ApplicationRecord
self.table_name = 'snip_stats'
def readonly?
true
end
end
Some read paths want a denormalized shape without materializing a new table. Postgres views are a clean option. Keep the view definition in a migration and map it with a read-only model.