rails/良く行う作業手順 の変更点
更新- 追加された行はこの色です。
- 削除された行はこの色です。
- ソフトウェア/rails/良く行う作業手順 へ行く。
- ソフトウェア/rails/良く行う作業手順 の差分を削除
[[公開メモ]] #contents * 概要 [#i14bc724] rails は便利なのですが、 たまにしか触らない「なんちゃって Web デベロッパー」としては、 そのつど rails の規約を思い出すのが苦痛なのです。 そこで、思い出せなかった手順をここにメモろうという魂胆です。 環境は Debian 上の apache2 上の fastcgi です。 * データベースにカラムを追加する [#h11a18ee] まずは現状を確認します。 sqlite3 の使い方はこちらを参照しました。 http://tterry.blog.so-net.ne.jp/2008-03-19-1 LANG:console $ sqlite3 db/production.sqlite3 sqlite3> .schema some_entries CREATE TABLE "some_entries" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "column1" integer, "column2" boolean, "column3" integer, "column4" boolean, "column5" date, "column6" date, "column7" integer, "column8" text, "column9" text, "column10" text, "column11" boolean, "changed_at" datetime, "created_at" datetime, "deleted" boolean DEFAULT 'f' NOT NULL); sqlite> .quit $ これまでのカラムの命名法を参考に、 フィールド名を column12 に決めたとします。 次にマイグレーション用のひな型を作って、それを編集します。 rake migrate の使い方はこちらを参照しました。 http://tech.feedforce.jp/railsmigration.html LANG:console $ ./script/generate migration add_column12_to_some_entries $ rails generate migration add_column12_to_some_entries exists db/migrate create db/migrate/20101018065146_add_column12_to_some_entries.rb $ jed db/migrate/20101018065146_add_column12_to_some_entries.rb class AddColumn12ToSomeEntries < ActiveRecord::Migration def self.up add_column :some_entries, :column12, :text end def self.down remove_column :some_entries, :column12, :text end end $ そしてマイグレーション。 LANG:console $ rake db:migrate (in /home/samba/www/event/rails/ICSPM18) == AddRegistrationsPayaccount: migrating ===================================== -- add_column(:registrations, :payaccount, :text) -> 0.0546s == AddRegistrationsPayaccount: migrated (0.0549s) ============================ $ これで development 環境が更新されます。 production 環境へも追加するなら、次を行うわけですが・・・ LANG:console $ rake RAILS_ENV=production db:migrate $ rails db:migrate RAILS_ENV=production (in /home/samba/www/event/rails/ICSPM18) == AddRegistrationsPayaccount: migrating ===================================== -- add_column(:registrations, :payaccount, :text) -> 0.0831s == AddRegistrationsPayaccount: migrated (0.0837s) ============================ $ これに気づかず1時間くらい考え込んだりするわけです(TT * データベースからカラムを削除する [#bdd160c9] 普通に考えると、 LANGUAGE:ruby class RemoveSomeColumnFromTheTable < ActiveRecord::Migration[5.1] def up remove_column :the_table, :some_column end def down add_column :the_table, :some_column, :column_type end end で良さそうに思えるのですが、古い ActiveRecord ではデータベースが sqlite3 だと LANGUAGE:console $ rails db:migrate ... -- remove_column(:the_table, :some_column) rails aborted! StandardError: An error has occurred, this and all later migrations canceled: SQLite3::ConstraintException: FOREIGN KEY constraint failed: DROP TABLE "the_table" などと言って migration が失敗してしまいます。 どうやら sqlite3 では remove_column がサポートされていないらしく、 内部では一旦 DROP TABLE してから新たに CREATE TABLE して、 データのコピーやらなんやらしているらしいのですが、 その際に外部キー制約がかかっていると制約違反でエラーになってしまうようで、、、 この問題は ActiveRecord の 6.0 以上では解決しているのだけれど、 5.x 系列ではうまく行かないのだそうです。 どうしたらいいかというと 6.0 のコードを参考にして LANGUAGE:ruby class RemoveSomeColumnFromTheTable < ActiveRecord::Migration[5.1] # sqlite は drop_column がないので一旦 drop table して # 作り直すことになるのだけれど、そのままやると foreign_key # 制約に引っかかるので PRAGMA foreign_keys でくくってやる # 必要がある。これをサポートしていない古い ActiveRecord の # ために、最新版のコードからもらってきて以下のようにした。 # https://my.diffend.io/gems/activerecord/4.2.11.3/6.0.0/page/34 def ignore_foreign_keys if ActiveRecord::Base.connection_config[:adapter] != 'sqlite3' yield # sqlite3 じゃなければ普通に実効 else # sqlite3 の場合は foreign key 制約を無効にしてから実効 old_foreign_keys = query_value("PRAGMA foreign_keys") old_defer_foreign_keys = query_value("PRAGMA defer_foreign_keys") begin execute("PRAGMA defer_foreign_keys = ON") execute("PRAGMA foreign_keys = OFF") yield ensure execute("PRAGMA defer_foreign_keys = #{old_defer_foreign_keys}") execute("PRAGMA foreign_keys = #{old_foreign_keys}") end end end def up ignore_foreign_keys do remove_column :the_table, :some_column end end def down add_column :the_table, :some_column, :column_type end end のように remove_column の前後で PRAGMA を変更して、 作業中に foreign_keys 制約を無視させれば良いようでした。 * エラーが出た時に参照すべきログファイル [#o9194703] apache2 のログファイルが /var/log/apache2/* にあるので、 まずはこれを参照します。 rails 固有のメッセージはプロジェクトフォルダの下の~ (rails)/log/*.log ~ にあるので、これを見ればよいようです。 * コメント [#a0b91bea] #article_kcaptcha
Counter: 6660 (from 2010/06/03),
today: 3,
yesterday: 2