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: 7017 (from 2010/06/03),
today: 1,
yesterday: 0