LoginSignup
7
3

More than 5 years have passed since last update.

シードをCSVで管理

Last updated at Posted at 2016-05-13

自分の備忘用

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を吐き出す。管理画面から入力したものを取り込みたいときに使う

7
3
5

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
7
3