自分の備忘用
db/seeds/items.csv
みたいにCSVファイルを用意
seeds.rb
csv_import_models =
if ENV['models']
ENV['models'].split(',')
else
%w(item company)
end
csv_import_models.each do |model_name|
puts const = model_name.camelize.constantize
const.transaction do
ids = []
CSV.foreach(
Rails.root.join("db/seeds/#{model_name.pluralize}.csv"),
headers: true
) do |csv_row|
ids << id = csv_row.to_hash['id']
record = const.find_or_initialize_by(id: id)
record.update!(csv_row.to_hash.select{|k, _| k.in?(const.column_names) })
puts "=> #{record.inspect}"
end
const.where.not(id: ids).destroy_all
ActiveRecord::Base.connection.execute("ALTER SEQUENCE #{model_name.pluralize}_id_seq RESTART WITH #{ids.map(&:to_i).max + 1}")
end
end
のようにしておく。CSVにはID列も入れることで何回流しも大丈夫なようになる
$ rake db:seed models=item,company
みたいに指定してシード更新可能
2016/5/19 追記
IDを含めてシードを流してもxxx_id_seqが1のままだったので、画面等、シード以外から新たにレコードを追加しようとするとID=1で追加しようとしてユニーク制約でエラーが出ていた(postgres)。
ALTER SEQUENCE ...
の部分追記
ActiveAdmin
module SeedExportable
def self.included(base)
base.send(:collection_action, :seed_csv) do
# model = base.instance_variable_get(:@resource)
model = base.config.resource_name.instance_variable_get(:@klass)
exclude_columns = %w(created_at updated_at)
csv = CSV.generate(force_quotes: true) do |csv_row|
columns = model.column_names.reject{|c| c.in?(exclude_columns) }
csv_row << columns
model.all.each do |r|
attributes = r.attributes.values_at(*columns)
# enum は 変換後の値が出るように
columns.each_with_index do |column, i|
if model.defined_enums[column]
attributes[i] = r.send(column.to_sym)
end
end
csv_row << attributes
end
end
send_data csv, filename: "#{model.to_s.tableize}.csv"
end
base.send(:action_item, :seed_csv, only: :index) do
link_to('シード用CSV出力', action: :seed_csv, format: :csv)
end
end
end
のようにモジュールを定義。
item.rb
ActiveAdmin.register Item do
include SeedExportable
でインクルードするとシード用のCSVを吐き出す。管理画面から入力したものを取り込みたいときに使う