1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

マイグレーションでcsvファイルをimportするときに気をつけること

Last updated at Posted at 2019-11-10

概要

  • 何をしたの?

次の手順でテーブルに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ファイルの中で一度しか動作しない

という予測を立ててみましたが、はっきりとした原因はわかりませんでした。

参考記事

  1. migration の中で model を触ったら必ず reset_column_information する
1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?