LoginSignup
57
59

More than 5 years have passed since last update.

RailsでMySQL VIEWを使うには?

Posted at

MySQL上でVIEWを生成し、RailsからはModelとして認識させて振る舞いたい等のケースを想定しています。

PostgreSQL等では rails_sql_views という必殺gemがあるので大丈夫なんですが、
MySQLでは残念ながらそういうのが無いのです。

migration時にSQLを実行してVIEWを作る

migrationでSQLを直接吐いてVIEWを作成します。
基本的にはこれだけで大丈夫です。

class CreateMyView < ActiveRecord::Migration
  def self.up
    execute <<-SQL
      CREATE VIEW my_view AS SELECT ...
    SQL
  end
  def self.down
    execute <<-SQL
      DROP VIEW my_view
    SQL
  end
end

テストDB/CI対策

通常通りmigrationが進めば問題ないのですが、rake test/spec 等で利用するテスト用のDBに対しては、
通常 rake db:test:prepare によってDBスキーマが準備されます。

A Guide to Testing Rails Applicationsによると

rake db:test:prepare
Check for pending migrations and load the test schema

となっています。どういうことかというと、

The rake db:migrate above runs any pending migrations on the development environment and updates db/schema.rb.
The rake db:test:load recreates the test database from the current db/schema.rb.
  • 開発環境のmigrationによって db/schema.rb が生成される
  • テストデータの準備などにはmigrationを行わず、db/schema.rbを参考にして一気にテーブル構造を準備する

といった動作がなされるということです。通常のケースであれば問題ないのですが、
今回のようなSQLを直接流しているような migration が含まれていた場合、
db/schema.rb からは正常にテーブルを再現できないケースがあります。
例えば、今回のケースだと my_view は物理テーブルとして作成されてしまう等です。
Travis等でテストをしている場合も同じ問題にあたると思います。

丁度、同じ問題にあたっている方がいらっしゃったので引用。

というわけでこの場合は、rake db:test:prepare を改造します。

# Rakefile
Rake::TaskManager.class_eval do
  def remove_task(task_name)
    @tasks.delete(task_name.to_s)
  end
end

# lib/tasks/db/test.rake
Rake.application.remove_task "db:test:prepare"

namespace :db do
  namespace :test do
    task :prepare do
      system("rake db:drop RAILS_ENV=test")
      system("rake db:create RAILS_ENV=test")
      system("rake db:migrate RAILS_ENV=test")
    end
  end
end

これでテスト用DBもmigrationで作成するようになるので、ひとまず動作できるはず。
Travis CIを利用している場合は上記対策をしておけばこれだけで問題ないです。

# .travis.yml
script: "bundle exec rake test/spec"

rake test/spec でテストが走る前に改造された db:test:prepare がタスクとして動作するってことですね。

57
59
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
57
59