目的
マスターデータをseed.rbに全部書くとすごい量になるので、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を設定してあげる←私はたまに忘れます...