LoginSignup
1
1

More than 5 years have passed since last update.

seed dataをCSVで管理する

Last updated at Posted at 2017-03-03

目的

マスターデータをseed.rbに全部書くとすごい量になるので、CSVとかで管理したい

参考サイト

シードをCSVで管理

やりたかったことはまさにこれだっ!
大変参考にさせていただきました。ありがとうございます。

実施してみる

参考サイト様のseeds.rbをほぼままコピペして実施
(さすがにモデル名っぽいところは、変更したりrequireを追加したり最低限なことだけは修正)

↓実施結果

PS C:\Users\KTakata\work\poke_app> bundle exec rake db:seed models=type
Type
=> #<Type id: 1, name: "Dark", jap_name: "悪", jap_name_kana: "あく", sort_num: 16, created_at: "2017-03-02 20:42:50", updated_at: "2017-03-02 20:42:50">
=> #<Type id: 2, name: "Steel", jap_name: "鋼", jap_name_kana: "はがね", sort_num: 17, created_at: "2017-03-02 20:42:50", updated_at: "2017-03-02 20:42:50">

...(略)...

=> #<Type id: 18, name: "Normal", jap_name: "ノーマル", jap_name_kana: "ノーマル", sort_num: 1, created_at: "2017-03-02 20:42:50", updated_at: "2017-03-02 20:42:50">
rake aborted!
ActiveRecord::StatementInvalid: SQLite3::SQLException: near "SEQUENCE": syntax error: ALTER SEQUENCE types_id_seq RESTART
 WITH 19
C:/Users/KTakata/work/poke_app/db/seeds.rb:29:in `block (2 levels) in <top (required)>'
C:/Users/KTakata/work/poke_app/db/seeds.rb:13:in `block in <top (required)>'
C:/Users/KTakata/work/poke_app/db/seeds.rb:10:in `each'
C:/Users/KTakata/work/poke_app/db/seeds.rb:10:in `<top (required)>'
Tasks: TOP => db:seed
(See full trace by running task with --trace)

なんか落ちた...と思ってたら普通にALTER SEQUENCEのあたりでSyntax Errorが出ていますね。

さすがに、そのままコピペはだめだったか...(笑)

SQLite3用に修正してみる

要は、最後のALTER SEQUENCEをSQLite3でも行えば良いということなので、
SQLite3のシーケンスを任意の値にするコードに対象のコードを入れ替えましょう

修正したコードがこちら

seeds.rb
require 'csv'

csv_import_models =
  if ENV['models']
    ENV['models'].split(',')
  else
    %w(type)
  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("UPDATE sqlite_sequence SET seq=#{ids.map(&:to_i).max} WHERE name='#{model_name.pluralize}'")
  end
end

ActiveRecord::Base.connection.execute...の部分ですが、SQLite3の場合はなくても、次レコードを追加したときはIdがきちんと振られてたので問題ないっぽい?

おまけ

SQLite3のシーケンス(autoincrement)を任意の値に変更(設定)するには
update sqlite_sequence set seq=数字 where name='テーブル名';で変更可能です。

実際やってみた結果↓

PS C:\Users\KTakata\work\poke_app> bundle exec rails db
SQLite version 3.15.2 2016-11-28 19:13:37
Enter ".help" for usage hints.
sqlite> .schema types
CREATE TABLE "types" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "jap_name" varchar, "jap_name_kana" varchar, "sort_num" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
sqlite>
sqlite> select * from types;
1|Dark|悪|あく|16|2017-03-02 20:42:50.221307|2017-03-02 20:42:50.221307
2|Steel|鋼|はがね|17|2017-03-02 20:42:50.242309|2017-03-02 20:42:50.242309
3|Fighting|格闘|かくとう|7|2017-03-02 20:42:50.247309|2017-03-02 20:42:50.247309
4|Dragon|ドラゴン|ドラゴン|15|2017-03-02 20:42:50.248310|2017-03-02 20:42:50.248310
5|Electric|電気|でんき|4|2017-03-02 20:42:50.250310|2017-03-02 20:42:50.250310
6|Ice|氷|こおり|6|2017-03-02 20:42:50.251310|2017-03-02 20:42:50.251310
7|Ghost|ゴースト|ゴースト|9|2017-03-02 20:42:50.258311|2017-03-02 20:42:50.258311
8|Psychic|エスパー|エスパー|10|2017-03-02 20:42:50.261311|2017-03-02 20:42:50.261311
9|Poison|毒|どく|14|2017-03-02 20:42:50.268312|2017-03-02 20:42:50.268312
10|Fire|炎|ほのお|2|2017-03-02 20:42:50.274312|2017-03-02 20:42:50.274312
11|Bug|虫|むし|13|2017-03-02 20:42:50.278313|2017-03-02 20:42:50.278313
12|Flying|飛行|ひこう|8|2017-03-02 20:42:50.283313|2017-03-02 20:42:50.283313
13|Ground|地面|じめん|12|2017-03-02 20:42:50.284313|2017-03-02 20:42:50.284313
14|Grass|草|くさ|5|2017-03-02 20:42:50.286313|2017-03-02 20:42:50.286313
15|Water|水|みず|3|2017-03-02 20:42:50.287313|2017-03-02 20:42:50.287313
16|Fairy|フェアリー|フェアリー|18|2017-03-02 20:42:50.288314|2017-03-02 20:42:50.288314
17|Rock|岩|いわ|11|2017-03-02 20:42:50.289314|2017-03-02 20:42:50.289314
18|Normal|ノーマル|ノーマル|1|2017-03-02 20:42:50.290314|2017-03-02 20:42:50.290314
sqlite>
sqlite> update sqlite_sequence set seq=29  where name='types';
sqlite>
sqlite> insert into types ('name', 'created_at', 'updated_at') values ('huga', '2017-03-02 20:42:50.221307', '2017-03-02 20:42:50.221307');
sqlite>
sqlite> select * from types;
1|Dark|悪|あく|16|2017-03-02 20:42:50.221307|2017-03-02 20:42:50.221307
2|Steel|鋼|はがね|17|2017-03-02 20:42:50.242309|2017-03-02 20:42:50.242309
3|Fighting|格闘|かくとう|7|2017-03-02 20:42:50.247309|2017-03-02 20:42:50.247309
4|Dragon|ドラゴン|ドラゴン|15|2017-03-02 20:42:50.248310|2017-03-02 20:42:50.248310
5|Electric|電気|でんき|4|2017-03-02 20:42:50.250310|2017-03-02 20:42:50.250310
6|Ice|氷|こおり|6|2017-03-02 20:42:50.251310|2017-03-02 20:42:50.251310
7|Ghost|ゴースト|ゴースト|9|2017-03-02 20:42:50.258311|2017-03-02 20:42:50.258311
8|Psychic|エスパー|エスパー|10|2017-03-02 20:42:50.261311|2017-03-02 20:42:50.261311
9|Poison|毒|どく|14|2017-03-02 20:42:50.268312|2017-03-02 20:42:50.268312
10|Fire|炎|ほのお|2|2017-03-02 20:42:50.274312|2017-03-02 20:42:50.274312
11|Bug|虫|むし|13|2017-03-02 20:42:50.278313|2017-03-02 20:42:50.278313
12|Flying|飛行|ひこう|8|2017-03-02 20:42:50.283313|2017-03-02 20:42:50.283313
13|Ground|地面|じめん|12|2017-03-02 20:42:50.284313|2017-03-02 20:42:50.284313
14|Grass|草|くさ|5|2017-03-02 20:42:50.286313|2017-03-02 20:42:50.286313
15|Water|水|みず|3|2017-03-02 20:42:50.287313|2017-03-02 20:42:50.287313
16|Fairy|フェアリー|フェアリー|18|2017-03-02 20:42:50.288314|2017-03-02 20:42:50.288314
17|Rock|岩|いわ|11|2017-03-02 20:42:50.289314|2017-03-02 20:42:50.289314
18|Normal|ノーマル|ノーマル|1|2017-03-02 20:42:50.290314|2017-03-02 20:42:50.290314
30|huga||||2017-03-02 20:42:50.221307|2017-03-02 20:42:50.221307

といった感じとなります。
※数字の部分は次に登録される数字-1を設定してあげる←私はたまに忘れます...

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