4
3

More than 3 years have passed since last update.

RailsでMySQLのviewテーブルをmigrationで管理する

Posted at

概要

Railsでは標準でviewテーブルをmigrationで管理することができない。
そこで、scenicというgemを使って実現する。

ただし、このgemは標準でPostgreSQLにしか対応していないので、scenic-mysql_adapterというgemも使ってMySQLで使えるようにする。

Installation

gemをインストール

以下を追記

Gemfile
gem 'scenic', '~> 1.5', '>= 1.5.4'
gem 'scenic-mysql_adapter', '~> 1.0', '>= 1.0.1'

Install

$ bundle install --path vendor/bundle/

scenic.rbの作成

config/initializers/scenic.rbを作成する

config/initializers/scenic.rb
require 'scenic/mysql_adapter'

Scenic.configure do |config|
  config.database = Scenic::Adapters::MySQL.new
end

Usage

migrationファイルを生成

以下はsearch_resultsというviewテーブルを作成する例。

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

生成された以下のファイルに、viewテーブルを作成するDDLのcreate文以外の箇所を記載する。

db/views/search_results_v01.sql
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

migrate

$ bundle exec rake db:migrate

テスト用テーブルの作成も忘れずに

$ bundle exec rake db:test:prepare

Updateする場合

以下を実行するとsearch_results_v02.sqlが作成されるので、新しいDDLを記載し、rake db:migrateする。

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

db/schema.rbも変更されるので確認すること。

ちなみに

scenic-mysql_adapterを導入せずにmigrateすると、テーブルは作成されるが以下のエラーが出る。

$ bundle exec rake db:migrate
rake aborted!
ActiveRecord::StatementInvalid: Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'current_schemas(false))
            ORDER BY c.oid' at line 11:             SELECT
              c.relname as viewname,
              pg_get_viewdef(c.oid) AS definition,
              c.relkind AS kind,
              n.nspname AS namespace
            FROM pg_class c
              LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
            WHERE
              c.relkind IN ('m', 'v')
              AND c.relname NOT IN (SELECT extname FROM pg_extension)
              AND n.nspname = ANY (current_schemas(false))
            ORDER BY c.oid

リンク

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3