All Projects → scenic-views → Scenic

scenic-views / Scenic

Licence: mit
Scenic is maintained by Derek Prior, Caleb Hearth, and you, our contributors.

Programming Languages

ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to Scenic

Activerecord Clean Db Structure
Automatic cleanup for the Rails db/structure.sql file (ActiveRecord/PostgreSQL)
Stars: ✭ 101 (-96.46%)
Mutual labels:  activerecord, database, postgres, rails
Rein
Database constraints made easy for ActiveRecord.
Stars: ✭ 657 (-77%)
Mutual labels:  activerecord, database, postgres, rails
Zero downtime migrations
Zero downtime migrations with ActiveRecord 3+ and PostgreSQL
Stars: ✭ 513 (-82.04%)
Mutual labels:  activerecord, database, postgres, rails
Squid
🦑 Provides SQL tagged template strings and schema definition functions.
Stars: ✭ 57 (-98%)
Mutual labels:  schema, sql, database, postgres
Reactive record
Generate ActiveRecord models for a pre-existing Postgres db
Stars: ✭ 132 (-95.38%)
Mutual labels:  sql, database, postgres, rails
Goose
A database migration tool. Supports SQL migrations and Go functions.
Stars: ✭ 2,112 (-26.05%)
Mutual labels:  schema, sql, database, postgres
Fluentmigrator
Fluent migrations framework for .NET
Stars: ✭ 2,636 (-7.7%)
Mutual labels:  sql, database, postgres
Counter culture
Turbo-charged counter caches for your Rails app.
Stars: ✭ 1,397 (-51.09%)
Mutual labels:  activerecord, database, rails
Seamless database pool
Add support for master/slave database clusters in ActiveRecord to improve performance.
Stars: ✭ 222 (-92.23%)
Mutual labels:  activerecord, database, rails
Clear
Advanced ORM between postgreSQL and Crystal
Stars: ✭ 220 (-92.3%)
Mutual labels:  sql, database, postgres
Graphjin
GraphJin - Build APIs in 5 minutes with GraphQL. An instant GraphQL to SQL compiler.
Stars: ✭ 1,264 (-55.74%)
Mutual labels:  sql, database, rails
Calculate All
calculate_all method for aggregate functions in Active Record
Stars: ✭ 118 (-95.87%)
Mutual labels:  activerecord, postgres, rails
Activerecord Postgres enum
Integrate PostgreSQL's enum data type into ActiveRecord's schema and migrations.
Stars: ✭ 227 (-92.05%)
Mutual labels:  activerecord, postgres, rails
Lol dba
lol_dba is a small package of rake tasks that scan your application models and displays a list of columns that probably should be indexed. Also, it can generate .sql migration scripts.
Stars: ✭ 1,363 (-52.28%)
Mutual labels:  sql, database, rails
Postguard
🐛 Statically validate Postgres SQL queries in JS / TS code and derive schemas.
Stars: ✭ 104 (-96.36%)
Mutual labels:  schema, sql, database
Electrocrud
Database CRUD Application Built on Electron | MySQL, Postgres, SQLite
Stars: ✭ 1,267 (-55.64%)
Mutual labels:  sql, database, postgres
Activerecord where assoc
Make ActiveRecord do conditions on your associations
Stars: ✭ 126 (-95.59%)
Mutual labels:  sql, activerecord, rails
Querybuilder
SQL query builder, written in c#, helps you build complex queries easily, supports SqlServer, MySql, PostgreSql, Oracle, Sqlite and Firebird
Stars: ✭ 2,111 (-26.09%)
Mutual labels:  sql, activerecord, database
Trilogy
TypeScript SQLite layer with support for both native C++ & pure JavaScript drivers.
Stars: ✭ 195 (-93.17%)
Mutual labels:  schema, sql, database
Ebean
Ebean ORM
Stars: ✭ 1,172 (-58.96%)
Mutual labels:  sql, database, postgres

Scenic

Scenic Landscape

Build Status Documentation Quality Reviewed by Hound

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

Using Scenic, you can bring the power of SQL views to your Rails application without having to switch your schema format to SQL. Scenic provides a convention for versioning views that keeps your migration history consistent and reversible and avoids having to duplicate SQL strings across migrations. As an added bonus, you define the structure of your view in a SQL file, meaning you get full SQL syntax highlighting in the editor of your choice and can easily test your SQL in the database console during development.

Scenic ships with support for PostgreSQL. The adapter is configurable (see Scenic::Configuration) and has a minimal interface (see Scenic::Adapters::Postgres) that other gems can provide.

So how do I install this?

If you're using Postgres, Add gem "scenic" to your Gemfile and run bundle install. If you're using something other than Postgres, check out the available third party adapters.

Great, how do I create a view?

You've got this great idea for a view you'd like to call search_results. You can create the migration and the corresponding view definition file with the following command:

$ rails generate scenic:view search_results
      create  db/views/search_results_v01.sql
      create  db/migrate/[TIMESTAMP]_create_search_results.rb

Edit the db/views/search_results_v01.sql file with the SQL statement that defines your view. In our example, this might look 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

The generated migration will contain a create_view statement. Run the migration, and baby, you got a view going. The migration is reversible and the schema will be dumped into your schema.rb file.

$ rake db:migrate

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

Here's where Scenic really shines. Run that same view generator once more:

$ rails generate scenic:view search_results
      create  db/views/search_results_v02.sql
      create  db/migrate/[TIMESTAMP]_update_search_results_to_version_2.rb

Scenic detected that we already had an existing search_results view at version 1, created a copy of that definition as version 2, and created a migration to update to the version 2 schema. All that's left for you to do is tweak the schema in the new definition and run the update_view migration.

What if I want to change a view without dropping it?

The update_view statement used by default will drop your view then create a new version of it.

This is not desirable when you have complicated hierarchies of views, especially when some of those views may be materialized and take a long time to recreate.

You can use replace_view to generate a CREATE OR REPLACE VIEW SQL statement.

See Postgres documentation on how this works: http://www.postgresql.org/docs/current/static/sql-createview.html

To start replacing a view run the generator like for a regular change:

$ rails generate scenic:view search_results
      create  db/views/search_results_v02.sql
      create  db/migrate/[TIMESTAMP]_update_search_results_to_version_2.rb

Now, edit the migration. It should look something like:

class UpdateSearchResultsToVersion2 < ActiveRecord::Migration
  def change
    update_view :search_results, version: 2, revert_to_version: 1
  end
end

Update it to use replace view:

class UpdateSearchResultsToVersion2 < ActiveRecord::Migration
  def change
    replace_view :search_results, version: 2, revert_to_version: 1
  end
end

Now you can run the migration like normal.

Can I use this view to back a model?

You bet! Using view-backed models can help promote concepts hidden in your relational data to first-class domain objects and can clean up complex ActiveRecord or ARel queries. As far as ActiveRecord is concerned, a view is no different than a table.

class SearchResult < ApplicationRecord
  belongs_to :searchable, polymorphic: true

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

Scenic even provides a scenic:model generator that is a superset of scenic:view. It will act identically to the Rails model generator except that it will create a Scenic view migration rather than a table migration.

There is no special base class or mixin needed. If desired, any code the model generator adds can be removed without worry.

$ rails generate scenic:model recent_status
      invoke  active_record
      create    app/models/recent_status.rb
      invoke    test_unit
      create      test/models/recent_status_test.rb
      create      test/fixtures/recent_statuses.yml
      create  db/views/recent_statuses_v01.sql
      create  db/migrate/20151112015036_create_recent_statuses.rb

What about materialized views?

Materialized views are essentially SQL queries whose results can be cached to a table, indexed, and periodically refreshed when desired. Does Scenic support those? Of course!

The scenic:view and scenic:model generators accept a --materialized option for this purpose. When used with the model generator, your model will have the following method defined as a convenience to aid in scheduling refreshes:

def self.refresh
  Scenic.database.refresh_materialized_view(table_name, concurrently: false, cascade: false)
end

This will perform a non-concurrent refresh, locking the view for selects until the refresh is complete. You can avoid locking the view by passing concurrently: true but this requires both PostgreSQL 9.4 and your view to have at least one unique index that covers all rows. You can add or update indexes for materialized views using table migration methods (e.g. add_index table_name) and these will be automatically re-applied when views are updated.

The cascade option is to refresh materialized views that depend on other materialized views. For example, say you have materialized view A, which selects data from materialized view B. To get the most up to date information in view A you would need to refresh view B first, then right after refresh view A. If you would like this cascading refresh of materialized views, set cascade: true when you refresh your materialized view.

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

Scenic gives you drop_view too:

def change
  drop_view :search_results, revert_to_version: 2
  drop_view :materialized_admin_reports, revert_to_version: 3, materialized: true
end

FAQs

Why do I get an error when querying a view-backed model with find, last, or first?

ActiveRecord's find method expects to query based on your model's primary key, but views do not have primary keys. Additionally, the first and last methods will produce queries that attempt to sort based on the primary key.

You can get around these issues by setting the primary key column on your Rails model like so:

class People < ApplicationRecord
  self.primary_key = :my_unique_identifier_field
end

Why is my view missing columns from the underlying table?

Did you create the view with SELECT [table_name].*? Most (possibly all) relational databases freeze the view definition at the time of creation. New columns will not be available in the view until the definition is updated once again. This can be accomplished by "updating" the view to its current definition to bake in the new meaning of *.

add_column :posts, :title, :string
update_view :posts_with_aggregate_data, version: 2, revert_to_version: 2

When will you support MySQL, SQLite, or other databases?

We have no plans to add first-party adapters for other relational databases at this time because we (the maintainers) do not currently have a use for them. It's our experience that maintaining a library effectively requires regular use of its features. We're not in a good position to support MySQL, SQLite or other database users.

Scenic does support configuring different database adapters and should be extendable with adapter libraries. If you implement such an adapter, we're happy to review and link to it. We're also happy to make changes that would better accommodate adapter gems.

We are aware of the following existing adapter libraries for Scenic which may meet your needs:

Please note that the maintainers of Scenic make no assertions about the quality or security of the above adapters.

About

Scenic is maintained by Derek Prior, Caleb Hearth, and you, our contributors.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].