20
18

More than 5 years have passed since last update.

seed_fuでCSVファイルからデータを作成する

Last updated at Posted at 2015-03-23

概要

Railsで初期データを作成する場合、seed_fuは便利なのですが、ユーザに初期データ作成を以下のようなseed_fuの形式で依頼するのは難しいものがあります。

user.rb
# coding: utf-8

User.seed do |s|
  s.id = 1
  s.name = '山田 花子'
  s.email = 'yamada@hogehoge.hoge'
  s.groups = Group.where(:name => ['部署1','部署2'])
end

そこで、ユーザにはCSVファイルでデータを作成してもらって、それを読み込むようにしてみます。

基本的な書き方は以下のようになります。

db/fixtures/import.rb
require 'csv'

# インポートファイルを読み込む
def import_read( file_name )
  lines = CSV.read("db/fixtures/#{Rails.env}/#{file_name}")
  lines.unshift([])  # index 0番目は空行を入れてスキップさせる

  lines.each_with_index do |line, idx|
    next unless line.length > 0

    yield(line, idx) if block_given?
  end
end

# CSVファイルの取込
import_read('hoge.csv') do |line, idx|
  Hoge.seed do |s|
    s.id      = idx
    s.column1 = line[0]
    s.column2 = line[1]
  end
end

サンプル

では、実際にどのように記述していくか、サンプルを掲示します。
テーブル構造などは、こちらを参照してください。

今回、development環境用に作成していますが、productionstagingと環境別にフォルダを分けてデータファイルを用意します。

取り込むCSVファイル

db/fixtures/development/ヘッダ.csv
文房具
自転車
書籍
db/fixtures/development/詳細.csv
文房具,えんぴつ,3
文房具,ボールペン,145
文房具,定規,-5
自転車,ビアンキ,3
自転車,GT,25
db/fixtures/development/部署.csv
総務部,組織の事務を扱う,
秘書課,役員を補佐する,総務部
広報課,情報発信を行う,総務部
人事部,社員情報を管理する,
人事一課,,人事部
人事二課,,人事部
db/fixtures/development/ユーザ.csv
山田 花子,yamada@hogehoge.hoge,秘書課
鈴木 一郎,suzuki@hogehoge.hoge,人事二課,広報課
田中 太郎,tanaka@hogehoge.hoge,人事一課
佐藤 次郎,sato@hogehoge.hoge,人事部,広報課
db/fixtures/development/ゲスト.csv
井上 直太郎,inoue@hogehoge.hoge
大谷 健太郎,ootani@hogehoge.hoge
松本 浩太郎,matsumoto@hogehoge.hoge

インポート用のRubyファイル

共通メソッド
今回、seed_fuを意識していますが、他でも使えるように、libに共通メソッドとして作成しています。

lib/import.rb
require 'csv'

#
# =データのImportをサポートするメソッド群
#
# Author::  Takaki-K
# Version:: 0.0.1
#
module Import

  # == CSVのインポートファイルを読み込む
  # 指定されたCSVファイルを読み込み、読み込んだデータを1行単位で配列に格納し、ブロックへ渡す。
  # ブロックへは、データ(配列)、Index(1~)を渡す。
  #
  # === 引数
  # - file_path ファイルパス
  # - file_name ファイル名称(省略可 デフォルト値=nil)
  # - header    ヘッダの有無(省略可 デフォルト値=false)
  #
  def self.csv_read( file_path, file_name=nil, header=false )
    file_path = File.expand_path(file_name, file_path) unless file_name.nil?

    lines = CSV.read(file_path)
    lines.unshift([]) unless header  # headerが無い場合は、index 0番目に空行を入れてスキップさせる

    lines.each_with_index do |line, idx|
      next if     idx == 0         # ヘッダ行は読み飛ばす
      next unless line.length > 0  # データが無い行は読み飛ばす

      yield(line, idx) if block_given?
    end
  end

end

seed_fu用の読み込みファイル
種類別に読み込みファイルを作成しています。

db/fixtures/data_resources.rb
require "#{Rails.root}/lib/import.rb"

# =データの取込

# データファイルを保存しているフォルダ
data_folder = "#{Rails.root}/db/fixtures/#{Rails.env}"

# ==ヘッダ情報の取込
Import.csv_read(data_folder, 'ヘッダ.csv') do |line, idx|
  Header.seed do |s|
    s.id    = idx
    s.title = line[0]
  end
end


# ==詳細情報の取込
Import.csv_read(data_folder, '詳細.csv') do |line, idx|
  Detail.seed do |s|
    s.id     = idx
    s.header = Header.find_by_title(line[0])
    s.name   = line[1]
    s.stock  = line[2]
  end
end
db/fixtures/human_resources.rb
require "#{Rails.root}/lib/import.rb"

# =人事情報の取込

# データファイルを保存しているフォルダ
data_folder = "#{Rails.root}/db/fixtures/#{Rails.env}"

# == 部署情報の取込
Import.csv_read(data_folder, '部署.csv') do |line, idx|
  Group.seed do |s|
    s.id    = idx
    s.name  = line[0]
    s.description = line[1]
    s.group = Group.find_by_name(line[2])
  end
end


# == ユーザ情報の取込
Import.csv_read(data_folder, 'ユーザ.csv') do |line, idx|
  User.seed do |s|
    s.id    = idx
    s.name  = line[0]
    s.email = line[1]
    line.shift(2)
    s.groups = Group.where(:name => line)
  end
end

# == ゲスト情報の取込
Import.csv_read(data_folder, 'ゲスト.csv') do |line, idx|
  Guest.seed do |s|
    s.id    = idx
    s.name  = line[0]
    s.email = line[1]
  end
end

取込

ここまでできれば、取り込むだけです。

bundle exec rake db:seed_fu RAILS_ENV=development

20
18
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
20
18