Notes on using Materialize Views in Rails
Article Table of Contents
I’ve been doing occasional work with Materialized views in Rails. Capturing some notes.
The Usual Steps #
copy/rename the view(s) I’m modifying #
increment the version number by 1: db/views/given_view_v04.sql
-> db/views/given_view_v05.sql
write migration for each updated view #
rails g migration update_given_view_to_version_5
# frozen_string_literal: true
class UpdateGivenViewToVersion5 < ActiveRecord::Migration[6.0]
def change
ActiveRecord::Base.connection.execute 'SET statement_timeout = 0'
update_view :given_view, version: 5, revert_to_version: 4, materialized: true
end
end
# app/models/given_view.rb
class GivenView < ApplicationRecord
belongs_to :other_thing
def self.refresh(concurrently: true)
Scenic.database.refresh_materialized_view(table_name, concurrently: concurrently, cascade: false)
end
def readonly?
true
end
end
# spec/models/given_view_spec.rb
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe GivenView, type: :model do
context 'v6 refinements' do
it "correctly filters out certain objects" do
object_to_be_excluded = create(
:object,
:refinement_1,
:refinement_2,
association: associated_object
)
described_class.refresh(concurrently: false)
expect(described_class.all.pluck(:id)).not_to include(object_to_be_excluded.id)
end
end