Table of Contents
Some days ago, I was requested to enable to load seed data from excel, by my client, in rails 4 project. I told that data to be edited should be managed in database, not excel. But he really requested excel, then I and he decided load data from tsv. Excel is functional, so TSV is appropriate.
Select data area and copy and paste with mouse, Excel data can be pasted as TSV data to text editor, and vise versa.
Environment
- Ubuntu 14.04 LTS
- Rails 4.1.8
- Ruby 2.2.2
Direction
- Create feature to load TSV data as a task, and enable to execute with
rake
. - On executing
rake db:seed
, execute the task to load TSV.
Usage
Instruction
rake seed_file:load TSV=aaa,bbb,ccc/ddd
で aaa.tsv
、 bbb.tsv
、 ccc/ddd.tsv
をこの順で取り込みます。 特別処理をするコードを書いていない場合は クラス Aaa
、Bbb
、Ccc::Ddd
が必要になります。
rake seed_file:load
を実行しても db/seeds/tsv
の下のすべての TSV を取り込むようにはなっていません。 進行中だったプロジェクトにおいて必要性を感じなかったので実装しませんでした。
Attention
- TSV は
db/seeds/tsv
ディレクトリ の下に モデル名のスネークケース + “.tsv” の形で配置されるものとします。 - TSV は 1行目をカラム名、2行目以降を値にします。 存在しないカラムが記述されている場合、そのカラムはデータベースに取り込まれません。
_memo
という存在しない名前のカラムを作って、備考として利用することも可能です。 - 一度取り込んだ id は変更しないこと。 id をもとに データ の新規作成・更新を行っているので、 id が変更されると意図せぬデータができます。
- 取り込んだデータの削除はできません。
Program
The following program creates TSV
object first, and read each line. It enables to load big file because it doesn’t load all TSV lines into RAM at once. In ruby, require 'csv'
gives us CSV Class that can handle TSV, but I wanted hash of column name and value, and didn’t want to write TSV handling process in main procedure, so I created TSV Class.
Code
Explanation
On executing rake seed_file:load
, start from the line includes task load:
. :environment
is required to use model classes. そこでは 環境変数 TSV
に渡された文字列をカンマで区切り、 load_tsv_aspect
を実行して データベースにインポートします。
load_tsv_aspect
surrounds load_tsv
with transaction.load_tsv
では 環境変数 TSV
に渡されていた名前に応じて処理を分けます。 基本的には 1つのTSVを1つのテーブルにロードするだけです。 しかし、 特別に表形式のほうがデータが管理しやすい場合で、そのほうがミスが少ない場合は 1つのTSVに3つのテーブルのデータを保存して管理します。 そういうときのために、 特殊なテーブルには専用の取り込みメソッドを使用します。 上のコードでは category_table
というのが 環境変数 TSV
に渡された場合に、 category_table.tsv
から 3つのテーブルにデータをインポートします。
一般的な場合の load_table_tsv
では、 カラムと値をチェックして、 指定されたカラムがテーブルにあればデータとして扱います。 TSVに記述されたカラムがなければ処理を行わないため、 _memo
といったカラムを作って、管理のための備考を追加することもできます。
Now, the task was created. Then, edit seeds.rb
.
seeds.rb
To import TSV when rake db:seed
is executed, add some codes to seeds.rb
. It’s the following 2 lines.
ENV['TSV']
で 取り込み対象の TSV を指定します。 そして Rake::Task['seed_file:load'].invoke
でタスクを実行して TSV を取り込みます。