Scenic Documentation

repository·main·Indexed 25 days ago

https://github.com/scenic-views/scenic

A Rails gem for managing database views and materialized views using versioned SQL files and standard ActiveRecord migrations. Scenic allows developers to treat SQL views as first-class domain objects via view-backed ActiveRecord models and provides generators for creating, updating, and dropping views, including support for concurrent and cascading refreshes of materialized views in PostgreSQL.

Tokens
1.2K
Snippets
7
Records
13
Agent score
86%

What's inside Scenic

  1. Update a view in-place using replace_view

    main

    By default, updating a view drops and recreates it. To update a view in place (using CREATE OR REPLACE VIEW) to preserve dependencies, use the --replace option with the generator. This produces a migration using the replace_view method.

    $ rails generate scenic:view search_results --replace
  2. Update an existing view

    main

    To change a view, run the scenic:view generator again with the same name. Scenic will detect the existing version, create a new versioned SQL file (e.g., _v02.sql), and generate a migration to update the view.

    $ rails generate scenic:view search_results
  3. Create a new database view

    main

    Use the scenic:view generator to create a new view. This generates a versioned SQL definition file in db/views/ and a migration file in db/migrate/.

    1. Run the generator: rails generate scenic:view <view_name>
    2. Edit the generated .sql file in db/views/ to define your SQL query.
    3. Run the migration: rake db:migrate.
    $ rails generate scenic:view search_results
  4. Work with Materialized Views

    main

    Scenic supports materialized views via the --materialized flag in the scenic:view or scenic:model generators.

    Refreshing Materialized Views

    If you use scenic:model, a .refresh method is added to the model class:

    # Non-concurrent refresh (locks the view)
    Model.refresh
    
    # Concurrent refresh (requires Postgres 9.4+ and a unique index)
    Model.refresh(concurrently: true)
    
    # Cascading refresh (refreshes dependent views)
    Model.refresh(cascade: true)

    Updating Materialized Views with side_by_side strategy

    Because materialized views cannot be updated in-place with REPLACE VIEW, use the --side-by-side option during generation. This creates a migration using the side_by_side strategy, which prepares the new version under a temporary name to minimize lock time.

    $ rails generate scenic:view search_results --materialized --side-by-side
  5. Create a view-backed ActiveRecord model

    main

    You can back an ActiveRecord model with a view. Use the scenic:model generator, which is a superset of scenic:view. It creates the model file and the versioned view definition/migration.

    Important Requirements:

    • Primary Key: Since views do not have primary keys, you must explicitly declare the primary key in your model to enable methods like find, first, or last.
    • Read-only: It is recommended to define readonly? as true to prevent Rails from attempting to save changes to the view.
    $ rails generate scenic:model recent_status
  6. Drop a view

    main

    To remove a view, use the drop_view method in a migration. You can specify the version to revert to and whether the view is materialized.

    class DropViews < ActiveRecord::Migration
      def change
        drop_view :search_results, revert_to_version: 2
        drop_view :materialized_admin_reports, revert_to_version: 3, materialized: true
      end
    end
  7. Use Scenic::Index for adapter extensions

    main

    The Scenic::Index class is an in-memory representation of a database index.

    Note: This class is intended for use by adapter gems and the schema dumper. It is not intended for use by general application code.

    It provides access to the object name, the index name, and the SQL definition used to create the index.

  8. Generate a Scenic view using the Rails generator

    main

    Scenic provides a Rails generator to create view definitions (SQL files) and the corresponding database migrations. This generator handles both the creation of new views and the generation of update migrations for existing views.

    To create a new view, use the scenic:view generator followed by the name of the view. This will create a file in db/views/ and a migration file in db/migrate/.