namespace :seed_file do
# class to handle CSV file
class XSV
XSV_ROOT = Rails.root.join('db', 'seeds', 'xsv')
# Yield each line as hash.
# ==== Example
# instance.each{|values|
# value = values['column_name']
# }
# ==== Note
# This method is usefull when handle too big tsv file,
# because this method doesn't load all tsv contents into memory,
# handle each line.
def each(&block)
File.open(@file_path) do |tsv|
columns = self.class.split_line(tsv.readline)
while !tsv.eof
values = self.class.split_line(tsv.readline)
kv = {}
columns.each_with_index{|column_name, index|
kv[column_name] = values[index]
}
yield kv
end
end
end
# Initialize.
# first column of xsv file should be column name array
# ==== Parameters
# * +file_name+ - xsv file name except extension
def initialize(file_name)
@file_path = File.join(XSV_ROOT, file_name)
end
protected
# Split tab separated value string into array
# ==== Parmeter
# * +line+ - tab separated value string
def self.split_line(line)
raise StandardException.new('Implement split_line function!');
end
end
# class to handle CSV file
class CSV < XSV
protected
# Split comma separated value string into array
# ==== Parmeter
# * +line+ - tab separated value string
def self.split_line(line)
return line.chomp.split(",")
end
end
# class to handle TSV file
class TSV < XSV
protected
# Split tab separated value string into array
# ==== Parmeter
# * +line+ - tab separated value string
def self.split_line(line)
return line.chomp.split("t")
end
end
class XSVFactory
def self.create_xsv(file_name)
case file_name[-3, 3].downcase
when 'csv'
return CSV.new(file_name)
when 'tsv'
return TSV.new(file_name)
else
raise StandardException.new('File format is invalid.')
end
end
end
# Load xsv file without transaction.
# ==== Parameter
# * +file_key_name+ - file key name, it can be leveled_experience_table or
# table name.
# * +type+ - `csv` or `tsv`
def load_xsv(file_name)
xsv = XSVFactory.create_xsv(file_name)
file_key_name = file_name[0, file_name.length - 4]
case file_name
when 'japan/food_maker.csv', 'japan/railway_company.csv', 'america/paper_company.csv'
load_company_csv(xsv, file_key_name)
else
load_table_xsv(xsv, file_key_name)
end
end
# Load tsv file with transaction
def load_xsv_aspect(file_key_name)
Rails.logger.info('start to load ' << file_key_name)
ActiveRecord::Base.transaction do
load_xsv(file_key_name)
end
Rails.logger.info('end to load ' << file_key_name)
end
def load_table_xsv(xsv, file_key_name)
model_class = file_key_name.classify.constantize
xsv.each{|values|
model = model_class.find_or_initialize_by(id: values['id'])
values.each{|key, value|
if model.has_attribute?(key)
model[key] = value
end
}
model.save!
}
end
def load_company_csv(xsv, file_key_name)
model_class = file_key_name.classify.constantize
xsv.each{|values|
model = model_class.find_or_initialize_by(id: values['id'])
values.each{|key, value|
if model.has_attribute?(key)
model[key] = value
end
}
model.order_number = model.id + model.sort
model.save!
}
end
desc "load seed file"
task load: :environment do
if ENV.has_key?('FILE')
tsv_names = ENV['FILE'].split(',')
tsv_names.each{|xsv_name|
load_xsv_aspect(xsv_name)
}
end
end
end