概要
- 何をしたの?
次の手順でテーブルにcsvデータをimportするマイグレーションファイルを書いて実行した。
1. foobarテーブルにfooフィールドとbarフィールドを追加する
2. foobarテーブルのfooフィールドとbarフィールドにcsvファイルのデータをimportする
-
何が起きた?
そのテーブルにそんなフィールドは無い旨のエラーが吐かれた。
ActiveModel::UnknownAttributeError: unknown attribute 'foo' for Foobar.
結論
マイグレーションの中で複数フィールドを追加してcsvファイルのデータをimportするときは、
フィールド追加のマイグレーションファイルを分けましょう。
環境
Ruby 2.2.2p95
Rails 4.2.2
mysql 5.7.12
修正後コード
add_foo_to_foobar.rb
class AddFooToFoobar < ActiveRecord::Migration
def change
add_column :foobar, :foo, :text
Foobar.reset_column_information
end
end
add_bar_to_foobar.rb
class AddBarToFoobar < ActiveRecord::Migration
def change
add_column :foobar, :bar, :text
Foobar.reset_column_information
end
end
add_data_to_foobar.rb
class AddDataToFoobar < ActiveRecord::Migration
def change
csv_data = []
CSV.read('./rawdata/foobar.csv', headers: true).each do |record|
csv_data << Foobar.new({
foo: record[0],
bar: record[1]
})
end
Foobar.import csv_data
end
end
1~3のファイルの順番でマイグレーションを行い、無事フィールドの追加・データのimportをすることができました。
修正前コード
以下の3パターンでコードを書いてマイグレーションを実行したところ、いずれもActiveModel::UnknownAttributeError:~
が発生し、正常にマイグレーションができませんでした。
①add_column
を2行続けて、.reset_column_information
を1回する
class AddColumnToFoobar < ActiveRecord::Migration
def change
add_column :foobar, :foo, :text
add_column :foobar, :bar, :text
Foobar.reset_column_information
end
end
②1ファイルの中でadd_column
.reset_column_information
を交互にする
class AddColumnToFoobar < ActiveRecord::Migration
def change
add_column :foobar, :foo, :text
Foobar.reset_column_information
add_column :foobar, :bar, :text
Foobar.reset_column_information
end
end
③change_table~
でカラムを2行追加したあとに.reset_column_information
を1回する
class AddColumnToFoobar < ActiveRecord::Migration
def change
change_table :foobar, bulk: true do |t|
t.string :foo
t.string :bar
end
Foobar.reset_column_information
end
end
-
.reset_column_information
が直前の追加したフィールドにしか作用していない -
.reset_column_information
は1ファイルの中で一度しか動作しない
という予測を立ててみましたが、はっきりとした原因はわかりませんでした。