概要
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