akishin999の日記

調べた事などを書いて行きます。

Rails で ReadOnly なデータベースを扱う場合のいろいろ

Rails で書き込みをしたくない参照専用の DB を扱った際に、間違えて更新してしまわないために変更した箇所を備忘録代わりにメモ。
バージョンは 3.2.13 です。

ActiveRecord

使っているのは Rails 3 なんですが、なんとなく Rails 4 の concerns っぽくしてみました。
まずは Model の concerns ディレクトリを作成。

$ mkdir -p app/models/concerns

作成したディレクトリを config/application.rb の autoload_paths に追加して自動ロードされるように設定します。

config.autoload_paths += %W(#{config.root}/app/models/concerns)

以下のような Module を作成。

  • app/models/concerns/readonlyable.rb

読み取り専用にしたい Model で作成した Module を include します。

# -*- coding: utf-8 -*-
class ReadOnlyModel < ActiveRecord::Base
  include Readonlyable
・
・
・

これで Model は OK のはず。
rails console で save や delete を呼ぶと ActiveRecord::ReadOnlyRecord が飛んできます。

参考サイト

以下を参考にさせて頂きました。

LunaTear: RailsでReadonlyなmodel
http://lunatear.net/archives/001089.html

Read only models in ActiveRecord - toamitkumar's Code Blog
http://toamitkumar.com/blog/2009/05/27/read-only-models-in-activerecord/

Test

rake で Test を実行した際に db:test:prepare が走り、テスト用 DB が Drop されてしまいます。
今回はテスト用 DB も Drop したくなかったので、以下のようにして db:test:prepare を無効にしました。

Rails アプリケーションの直下にある Rakefile を開き、load_tasks より前の辺りに以下を追記します。

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

次に、lib/tasks/db/test.rake ファイルを作成します。

% mkdir lib/tasks/db
% vim lib/tasks/db/test.rake

以下の内容を記述します。

Rake.application.remove_task 'db:test:prepare'

namespace :db do
  namespace :test do
    task :prepare do |t|
      # rewrite the task to not do anything you don't want
      puts "Override db:test:prepare to NOT run drop database"
    end
  end
end

これで bundle exec rake を実行しても db:test:prepare が実行されないため、テスト用データベースに入れておいた値が消えなくなります。

参考

以下を参考にさせて頂きました。

kennyjのブログ(仮): spec実行時にdb:test:prepareを呼び出したくない。
http://kennyj-jp.blogspot.jp/2011/09/specdbtestprepare.html

ruby on rails - How to prevent Rake test to call task db:test:prepare - Stack Overflow
http://stackoverflow.com/questions/1097845/how-to-prevent-rake-test-to-call-task-dbtestprepare/1101325#1101325

Capistrano

Capistrano も deploy:cold 実行時などに deploy:migrate が呼ばれてマイグレーションが実行されます。
オペミスなどでこれらのタスクを間違えて実行してしまう可能性も排除したかったので、タスク自体を無効化しました。

deploy.rb に以下を追記します。

namespace(:deploy) do
  [:cold, :migrate, :migrations, ].each { |t|
    task(t) {
      puts "#{t} is disabled."
    }
  }
end

定義後に cap -T を実行してみるとタスクが表示されなくなり、無効化されていることが分かります。

参考

CakePHP2アプリケーションをCapistranoでデプロイする | Ryuzee.com
http://www.ryuzee.com/contents/blog/6119


これだけやっておけば大丈夫かな。