Scenic

Boston cityscape - it's scenic

Scenic (v0.2.0) is in an early stage of development. While it hasn't been tested in an actual application, we are relatively confident in its readiness and value, and stand ready to help resolve any issues it may have

Description

Scenic adds methods to ActiveRecord::Migration to create and manage database views in Rails.

Using Scenic, you can use the power of SQL views in your Rails application without having to switch your schema format to SQL. Scenic also handles versioning your views in a way that eliminates duplication across migrations. As an added bonus, you define the structure of your view in a SQL file, meaning you get full SQL syntax highlighting support in the editor of your choice.

Great, how do I create a view?

You've got this great idea for a view you'd like to call searches. Create a definition file at db/views/searches_v01.sql which contains the query you'd like to build your view with. Perhaps that looks something like this:

SELECT
  statuses.id AS searchable_id,
  'Status' AS searchable_type,
  comments.body AS term
FROM statuses
JOIN comments ON statuses.id = comments.status_id

UNION

SELECT
  statuses.id AS searchable_id,
  'Status' AS searchable_type,
  statuses.body AS term
FROM statuses

Generate a new migration with the following change method:

def change
  create_view :searches
end

Run that migration and congrats, you've got yourself a view. The migration is reversible and it will be dumped into your schema.rb file.

Cool, but what if I need to change that view?

Add the new query to db/views/searches_v02.sql and generate a new migration with the following change method:

def change
  update_view :searches, version: 2, revert_to_version: 1
end

When you run that migration, your view will be updated. The revert_to_version option makes that migration reversible.

Can I use this view to back a model?

You bet!

class Search < ActiveRecord::Base
  private

  # this isn't strictly necessary, but it will prevent
  # rails from calling save, which would fail anyway.
  def readonly?
    true
  end
end

Can you make this easier?

Sure thing. How about some generators?

Model generator

The scenic:model generator builds you a model, view, and migration from scratch. db/views/[model]_v01.sql wil be an empty file that you fill in only the query portion of the view with.

$ rails generate scenic:model search
      create  app/models/search.rb
      create  db/views/searches_v01.sql
      create  db/migrate/[TIMESTAMP]_create_searches.rb

View generator

The scenic:view generator is functionally equivalent to scenic:model except that it doesn't create the model. Convenient.

$ rails generate scenic:view search
      create  db/views/searches_v01.sql
      create  db/migrate/[TIMESTAMP]_create_searches.rb

Subsequent invocations will create updated view versions and update migrations:

rails generate scenic:view search
      create  db/views/searches_v02.sql
      create  db/migrate/[TIMESTAMP]_update_searches_to_version_2.rb

I don't need this view anymore. Make it go away.

We give you drop_view too:

def change
  drop_view :searches, revert_to_version: 2
end