Slide 1

Slide 1 text

seeds.rbΛॻ͔ ず ʹ ։ൃ؀ڥ デ ʔλΛ੔උ͢Δ @gogutan Kaigi on Rails 2023 Day1 10.27(Fri.)

Slide 2

Slide 2 text

ࣗݾ঺հ • @gogutan • झຯ : ӳޠɺڝϓϩ(AtCoder)ɺ ໺ٿ؍ઓ • FJORD BOOT CAMPग़਎ • Tech Lead @ גࣜձࣾΩϟλϧ

Slide 3

Slide 3 text

Seedσʔλͷϝϯςφϯε ͯ͠·͔͢ʁ

Slide 4

Slide 4 text

db/seeds.rbͱ͸ # db/seeds.rb

Slide 5

Slide 5 text

db/seeds.rbͱ͸ # db/seeds.rb Book.create!( title: 'ֶ໰ͷ͢͢Ί', author: '෱୔་٢' )

Slide 6

Slide 6 text

db/seeds.rbͱ͸ # db/seeds.rb Book.create!( title: 'ֶ໰ͷ͢͢Ί', author: '෱୔་٢' ) % rails db:seed

Slide 7

Slide 7 text

db/seeds.rbͱ͸ # db/seeds.rb Book.create!( title: 'ֶ໰ͷ͢͢Ί', author: '෱୔་٢' ) % rails db:seed % rails c

Slide 8

Slide 8 text

db/seeds.rbͱ͸ # db/seeds.rb Book.create!( title: 'ֶ໰ͷ͢͢Ί', author: '෱୔་٢' ) % rails db:seed % rails c irb(main):001> Book.first

Slide 9

Slide 9 text

db/seeds.rbͱ͸ # db/seeds.rb Book.create!( title: 'ֶ໰ͷ͢͢Ί', author: '෱୔་٢' ) % rails db:seed % rails c irb(main):001> Book.first => # ॳظσʔλΛ؆୯ʹ ༻ҙͰ͖ͯخ͍͠😊

Slide 10

Slide 10 text

ҙ֎ͱϝϯςφϯε͕೉͍͠😥

Slide 11

Slide 11 text

ྫ͑͹ɺBookʹCommentΛ ෇͚Δػೳ͕͋ͬͨ࣌

Slide 12

Slide 12 text

SeedσʔλʹComment͕ແͯ͘΋ ͦΕ΄ͲࠔΒͳ͍

Slide 13

Slide 13 text

Ͱ΋CommentΛຖճ खಈͰ࡞͍ͬͯΔΑ͏ͳ…

Slide 14

Slide 14 text

ෳࡶͳϦϨʔγϣϯ΍ίʔϧόοΫ… खΛ෇͚ʹ͍͘͜ͱ΋͋Δ

Slide 15

Slide 15 text

݁Ռͱͯ͠ى͜ΓಘΔ͜ͱ • ֤ΤϯδχΞ͕ϩʔΧϧ؀ڥʹಠࣗͷσʔλΛੵΈॏͶΔ 
 (஌ݟ͕ڞ༗͞Εʹ͘͘ͳΔ) • Pull Requestຖͷݕূ؀ڥͷσʔλ͕खബʹͳΔ 
 (ಈ࡞֬ೝ΍σʔλͷϦετΞʹ͕͔͔࣌ؒΔ)

Slide 16

Slide 16 text

݁Ռͱͯ͠ى͜ΓಘΔ͜ͱ • ֤ΤϯδχΞ͕ϩʔΧϧ؀ڥʹಠࣗͷσʔλΛੵΈॏͶΔ 
 (஌ݟ͕ڞ༗͞Εʹ͘͘ͳΔ) • Pull Requestຖͷݕূ؀ڥͷσʔλ͕खബʹͳΔ 
 (ಈ࡞֬ೝ΍σʔλͷϦετΞʹ͕͔͔࣌ؒΔ) 
 
 →νʔϜશମͷ։ൃޮ཰͕མͪΔ🫠

Slide 17

Slide 17 text

100ۙ͋͘ΔϞσϧͷ͏ͪɺ Seedσʔλ͕ଘࡏ͢Δͷ͸4ׂఔ౓😢

Slide 18

Slide 18 text

खΛ෇͚Δͷ͕೉ͦ͠͏ͳྫ🤯 • εέδϡʔϥʔܥͷϞσϧʢຖिͷϨοεϯ೔࣌ͳͲʣ • ཤྺ؅ཧܥͷϞσϧʢੜెͷϨϕϧΞοϓͷ؅ཧͳͲʣ • ͦͷ࣌఺ͷσʔλΛϋʔυίϐʔ͢ΔܥͷϞσϧ 
 ʢϨοεϯͰऔΓ૊ΉΧϦΩϡϥϜͳͲʣ 


Slide 19

Slide 19 text

ࠓϩʔΧϧʹ͋ΔΑ͏ͳσʔλ͕ ཉ͍͚ͩ͠ͳΜ͚ͩͲͳʙ😌

Slide 20

Slide 20 text

# db/fixtures/01_books.rb require 'csv' books = [] CSV.foreach('db/fixtures/books.csv').with_index do |row, i| next if i.zero? books << { id: row[0], title: row[1], author: row[2], created_at: row[3], updated_at: row[4] } end Book.insert_all books # db/fixtures/books.csv id,title,author,created_at,updated_at 1,ֶ໰ͷ͢͢Ί,෱୔་٢,2022-06-20 10:44,2022-06-20 10:44 2,ҏ౾ͷགྷΓࢠ,઒୺߁੒,2022-06-20 10:44,2022-06-20 10:44 CSV͔ΒSeed͍ͯ͠Δ ϞσϧΛൃݟ👀

Slide 21

Slide 21 text

Ͱ͖ΔͷͰ͸ʂʁ🤨

Slide 22

Slide 22 text

seeds.rbΛॻ͔ͳ͍࡞ઓͷ֓ཁ • ϩʔΧϧͰΞϓϦΛૢ࡞͍͍ͯ͠ײ͡ͷσʔλΛ༻ҙ͢Δ • CSVϑΝΠϧʹશͯͷϨίʔυΛग़ྗ͢Δ • rails db:seed࣌ɺCSVϑΝΠϧΛݩʹόϧΫΠϯαʔτ͢Δ

Slide 23

Slide 23 text

࣮ફ👀

Slide 24

Slide 24 text

seeds.rbΛॻ͔ͳ͍࡞ઓͷ֓ཁ • ϩʔΧϧͰΞϓϦΛૢ࡞͍͍ͯ͠ײ͡ͷσʔλΛ༻ҙ͢Δ • CSVϑΝΠϧʹશͯͷϨίʔυΛग़ྗ͢Δ • rails db:seed࣌ɺCSVϑΝΠϧΛݩʹόϧΫΠϯαʔτ͢Δ

Slide 25

Slide 25 text

ϩʔΧϧʹ͍͍ײ͡ͷ σʔλΛ༻ҙ BooksΞϓϦʹ2ߦొ࿥ࡁ

Slide 26

Slide 26 text

seeds.rbΛॻ͔ͳ͍࡞ઓͷ֓ཁ • ϩʔΧϧͰΞϓϦΛૢ࡞͍͍ͯ͠ײ͡ͷσʔλΛ༻ҙ͢Δ • CSVϑΝΠϧʹશͯͷϨίʔυΛग़ྗ͢Δ • rails db:seed࣌ɺCSVϑΝΠϧΛݩʹόϧΫΠϯαʔτ͢Δ

Slide 27

Slide 27 text

# lib/tasks/generate_csv_from_db.rake require 'csv' desc 'for generating csv from db' task :generate_csv_from_db => :environment do |_task, args| def generate_csv(model_name) model = model_name.constantize results = model.pluck(*model.column_names) return 0 if results.size.zero? data = CSV.generate do |csv| csv << model.column_names results.each { |result| csv << result } end file_path = "db/fixtures/bulk_insert/#{model_name}.csv" File.open(file_path, 'w') do |file| file.write(data) p "Finished generating #{file_path}(#{results.size} rows) from DB!” end return results.size end total_count = 0 ActiveRecord::Base.connection .tables .each { |t| total_count += generate_csv(t.classify) } p "Total row count: #{total_count}" end end CSVʹશϨίʔυग़ྗ

Slide 28

Slide 28 text

# lib/tasks/generate_csv_from_db.rake require 'csv' desc 'for generating csv from db' task :generate_csv_from_db => :environment do |_task, args| def generate_csv(model_name) model = model_name.constantize results = model.pluck(*model.column_names) return 0 if results.size.zero? data = CSV.generate do |csv| csv << model.column_names results.each { |result| csv << result } end file_path = "db/fixtures/bulk_insert/#{model_name}.csv" File.open(file_path, 'w') do |file| file.write(data) p "Finished generating #{file_path}(#{results.size} rows) from DB!” end return results.size end total_count = 0 ActiveRecord::Base.connection .tables .each { |t| total_count += generate_csv(t.classify) } p "Total row count: #{total_count}" end end CSVʹશϨίʔυग़ྗ

Slide 29

Slide 29 text

# lib/tasks/generate_csv_from_db.rake require 'csv' desc 'for generating csv from db' task :generate_csv_from_db => :environment do |_task, args| def generate_csv(model_name) model = model_name.constantize results = model.pluck(*model.column_names) return 0 if results.size.zero? data = CSV.generate do |csv| csv << model.column_names results.each { |result| csv << result } end file_path = "db/fixtures/bulk_insert/#{model_name}.csv" File.open(file_path, 'w') do |file| file.write(data) p "Finished generating #{file_path}(#{results.size} rows) from DB!” end return results.size end total_count = 0 ActiveRecord::Base.connection .tables .each { |t| total_count += generate_csv(t.classify) } p "Total row count: #{total_count}" end end CSVʹશϨίʔυग़ྗ

Slide 30

Slide 30 text

# lib/tasks/generate_csv_from_db.rake require 'csv' desc 'for generating csv from db' task :generate_csv_from_db => :environment do |_task, args| def generate_csv(model_name) model = model_name.constantize results = model.pluck(*model.column_names) return 0 if results.size.zero? data = CSV.generate do |csv| csv << model.column_names results.each { |result| csv << result } end file_path = "db/fixtures/bulk_insert/#{model_name}.csv" File.open(file_path, 'w') do |file| file.write(data) p "Finished generating #{file_path}(#{results.size} rows) from DB!” end return results.size end total_count = 0 ActiveRecord::Base.connection .tables .each { |t| total_count += generate_csv(t.classify) } p "Total row count: #{total_count}" end end CSVʹશϨίʔυग़ྗ

Slide 31

Slide 31 text

# lib/tasks/generate_csv_from_db.rake require 'csv' desc 'for generating csv from db' task :generate_csv_from_db => :environment do |_task, args| def generate_csv(model_name) model = model_name.constantize results = model.pluck(*model.column_names) return 0 if results.size.zero? data = CSV.generate do |csv| csv << model.column_names results.each { |result| csv << result } end file_path = "db/fixtures/bulk_insert/#{model_name}.csv" File.open(file_path, 'w') do |file| file.write(data) p "Finished generating #{file_path}(#{results.size} rows) from DB!” end return results.size end total_count = 0 ActiveRecord::Base.connection .tables .each { |t| total_count += generate_csv(t.classify) } p "Total row count: #{total_count}" end end CSVʹશϨίʔυग़ྗ

Slide 32

Slide 32 text

# lib/tasks/generate_csv_from_db.rake require 'csv' desc 'for generating csv from db' task :generate_csv_from_db => :environment do |_task, args| def generate_csv(model_name) model = model_name.constantize results = model.pluck(*model.column_names) return 0 if results.size.zero? data = CSV.generate do |csv| csv << model.column_names results.each { |result| csv << result } end file_path = "db/fixtures/bulk_insert/#{model_name}.csv" File.open(file_path, 'w') do |file| file.write(data) p "Finished generating #{file_path}(#{results.size} rows) from DB!” end return results.size end total_count = 0 ActiveRecord::Base.connection .tables .each { |t| total_count += generate_csv(t.classify) } p "Total row count: #{total_count}" end end CSVʹશϨίʔυग़ྗ

Slide 33

Slide 33 text

# lib/tasks/generate_csv_from_db.rake require 'csv' desc 'for generating csv from db' task :generate_csv_from_db => :environment do |_task, args| def generate_csv(model_name) model = model_name.constantize results = model.pluck(*model.column_names) return 0 if results.size.zero? data = CSV.generate do |csv| csv << model.column_names results.each { |result| csv << result } end file_path = "db/fixtures/bulk_insert/#{model_name}.csv" File.open(file_path, 'w') do |file| file.write(data) p "Finished generating #{file_path}(#{results.size} rows) from DB!” end return results.size end total_count = 0 ActiveRecord::Base.connection .tables .each { |t| total_count += generate_csv(t.classify) } p "Total row count: #{total_count}" end end CSVʹશϨίʔυग़ྗ id,title,author,created_at,updated_at 1,ֶ໰ͷ͢͢Ί,෱୔་٢,2021/02/01 12:33,2021/02/01 12:33 2,ҏ౾ͷགྷΓࢠ,઒୺߁੒,2021/02/01 12:33,2021/02/01 12:33 …… ←

Slide 34

Slide 34 text

# lib/tasks/generate_csv_from_db.rake require 'csv' desc 'for generating csv from db' task :generate_csv_from_db => :environment do |_task, args| def generate_csv(model_name) model = model_name.constantize results = model.pluck(*model.column_names) return 0 if results.size.zero? data = CSV.generate do |csv| csv << model.column_names results.each { |result| csv << result } end file_path = "db/fixtures/bulk_insert/#{model_name}.csv" File.open(file_path, 'w') do |file| file.write(data) p "Finished generating #{file_path}(#{results.size} rows) from DB!” end return results.size end total_count = 0 ActiveRecord::Base.connection .tables .each { |t| total_count += generate_csv(t.classify) } p "Total row count: #{total_count}" end end CSVʹશϨίʔυग़ྗ id,title,author,created_at,updated_at 1,ֶ໰ͷ͢͢Ί,෱୔་٢,2021/02/01 12:33,2021/02/01 12:33 2,ҏ౾ͷགྷΓࢠ,઒୺߁੒,2021/02/01 12:33,2021/02/01 12:33 ……

Slide 35

Slide 35 text

# lib/tasks/generate_csv_from_db.rake require 'csv' desc 'for generating csv from db' task :generate_csv_from_db => :environment do |_task, args| def generate_csv(model_name) model = model_name.constantize results = model.pluck(*model.column_names) return 0 if results.size.zero? data = CSV.generate do |csv| csv << model.column_names results.each { |result| csv << result } end file_path = "db/fixtures/bulk_insert/#{model_name}.csv" File.open(file_path, 'w') do |file| file.write(data) p "Finished generating #{file_path}(#{results.size} rows) from DB!” end return results.size end total_count = 0 ActiveRecord::Base.connection .tables .each { |t| total_count += generate_csv(t.classify) } p "Total row count: #{total_count}" end end CSVʹશϨίʔυग़ྗ id,title,author,created_at,updated_at 1,ֶ໰ͷ͢͢Ί,෱୔་٢,2021/02/01 12:33,2021/02/01 12:33 2,ҏ౾ͷགྷΓࢠ,઒୺߁੒,2021/02/01 12:33,2021/02/01 12:33 ……

Slide 36

Slide 36 text

# lib/tasks/generate_csv_from_db.rake require 'csv' desc 'for generating csv from db' task :generate_csv_from_db => :environment do |_task, args| def generate_csv(model_name) model = model_name.constantize results = model.pluck(*model.column_names) return 0 if results.size.zero? data = CSV.generate do |csv| csv << model.column_names results.each { |result| csv << result } end file_path = "db/fixtures/bulk_insert/#{model_name}.csv" File.open(file_path, 'w') do |file| file.write(data) p "Finished generating #{file_path}(#{results.size} rows) from DB!” end return results.size end total_count = 0 ActiveRecord::Base.connection .tables .each { |t| total_count += generate_csv(t.classify) } p "Total row count: #{total_count}" end end CSVʹશϨίʔυग़ྗ id,title,author,created_at,updated_at 1,ֶ໰ͷ͢͢Ί,෱୔་٢,2021/02/01 12:33,2021/02/01 12:33 2,ҏ౾ͷགྷΓࢠ,઒୺߁੒,2021/02/01 12:33,2021/02/01 12:33 ……

Slide 37

Slide 37 text

# lib/tasks/generate_csv_from_db.rake require 'csv' desc 'for generating csv from db' task :generate_csv_from_db => :environment do |_task, args| def generate_csv(model_name) model = model_name.constantize results = model.pluck(*model.column_names) return 0 if results.size.zero? data = CSV.generate do |csv| csv << model.column_names results.each { |result| csv << result } end file_path = "db/fixtures/bulk_insert/#{model_name}.csv" File.open(file_path, 'w') do |file| file.write(data) p "Finished generating #{file_path}(#{results.size} rows) from DB!” end return results.size end total_count = 0 ActiveRecord::Base.connection .tables .reject{ |t| t.in? %w(schema_migrations ar_internal_metadata) } .each { |t| total_count += generate_csv(t.classify) } p "Total row count: #{total_count}" end end CSVʹશϨίʔυग़ྗ id,title,author,created_at,updated_at 1,ֶ໰ͷ͢͢Ί,෱୔་٢,2021/02/01 12:33,2021/02/01 12:33 2,ҏ౾ͷགྷΓࢠ,઒୺߁੒,2021/02/01 12:33,2021/02/01 12:33 …… ←

Slide 38

Slide 38 text

rakeλεΫ࣮ߦ % rails generate_csv_from_db

Slide 39

Slide 39 text

rakeλεΫ࣮ߦ % rails generate_csv_from_db "Finished generating db/fixtures/bulk_insert/Book.csv (2 rows) from DB!" "Total row count: 2"

Slide 40

Slide 40 text

rakeλεΫ࣮ߦ % rails generate_csv_from_db "Finished generating db/fixtures/bulk_insert/Book.csv (2 rows) from DB!" "Total row count: 2" CSVΛແࣄʹੜ੒🙌

Slide 41

Slide 41 text

seeds.rbΛॻ͔ͳ͍࡞ઓͷ֓ཁ • ϩʔΧϧͰΞϓϦΛૢ࡞͍͍ͯ͠ײ͡ͷσʔλΛ༻ҙ͢Δ • CSVϑΝΠϧʹશͯͷϨίʔυΛग़ྗ͢Δ • rails db:seed࣌ɺCSVϑΝΠϧΛݩʹόϧΫΠϯαʔτ͢Δ

Slide 42

Slide 42 text

# db/seeds.rb require 'csv' file_paths = Dir.glob('db/fixtures/bulk_insert/*.csv') file_paths.each do |file_path| csv = CSV.table(file_path) ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize model.insert_all! csv.map(&:to_hash) table_name = model.table_name p "Finished inserting #{csv.size} records into #{table_name} table!" end end CSV͔ΒόϧΫΠϯαʔτ

Slide 43

Slide 43 text

# db/seeds.rb require 'csv' file_paths = Dir.glob('db/fixtures/bulk_insert/*.csv') file_paths.each do |file_path| csv = CSV.table(file_path) ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize model.insert_all! csv.map(&:to_hash) table_name = model.table_name p "Finished inserting #{csv.size} records into #{table_name} table!" end end CSV͔ΒόϧΫΠϯαʔτ

Slide 44

Slide 44 text

# db/seeds.rb require 'csv' file_paths = Dir.glob('db/fixtures/bulk_insert/*.csv') file_paths.each do |file_path| csv = CSV.table(file_path) ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize model.insert_all! csv.map(&:to_hash) table_name = model.table_name p "Finished inserting #{csv.size} records into #{table_name} table!" end end CSV͔ΒόϧΫΠϯαʔτ

Slide 45

Slide 45 text

# db/seeds.rb require 'csv' file_paths = Dir.glob('db/fixtures/bulk_insert/*.csv') file_paths.each do |file_path| csv = CSV.table(file_path) ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize model.insert_all! csv.map(&:to_hash) table_name = model.table_name p "Finished inserting #{csv.size} records into #{table_name} table!" end end CSV͔ΒόϧΫΠϯαʔτ

Slide 46

Slide 46 text

# db/seeds.rb require 'csv' file_paths = Dir.glob('db/fixtures/bulk_insert/*.csv') file_paths.each do |file_path| csv = CSV.table(file_path) ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize model.insert_all! csv.map(&:to_hash) table_name = model.table_name p "Finished inserting #{csv.size} records into #{table_name} table!" end end CSV͔ΒόϧΫΠϯαʔτ

Slide 47

Slide 47 text

# db/seeds.rb require 'csv' file_paths = Dir.glob('db/fixtures/bulk_insert/*.csv') file_paths.each do |file_path| csv = CSV.table(file_path) ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize model.insert_all! csv.map(&:to_hash) table_name = model.table_name p "Finished inserting #{csv.size} records into #{table_name} table!" end end CSV͔ΒόϧΫΠϯαʔτ

Slide 48

Slide 48 text

# db/seeds.rb require 'csv' file_paths = Dir.glob('db/fixtures/bulk_insert/*.csv') file_paths.each do |file_path| csv = CSV.table(file_path) ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize model.insert_all! csv.map(&:to_hash) table_name = model.table_name p "Finished inserting #{csv.size} records into #{table_name} table!" end end CSV͔ΒόϧΫΠϯαʔτ

Slide 49

Slide 49 text

# db/seeds.rb require 'csv' file_paths = Dir.glob('db/fixtures/bulk_insert/*.csv') file_paths.each do |file_path| csv = CSV.table(file_path) ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize model.insert_all! csv.map(&:to_hash) table_name = model.table_name p "Finished inserting #{csv.size} records into #{table_name} table!" end end CSV͔ΒόϧΫΠϯαʔτ

Slide 50

Slide 50 text

# db/seeds.rb require 'csv' file_paths = Dir.glob('db/fixtures/bulk_insert/*.csv') file_paths.each do |file_path| csv = CSV.table(file_path) ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize model.insert_all! csv.map(&:to_hash) table_name = model.table_name p "Finished inserting #{csv.size} records into #{table_name} table!" end end CSV͔ΒόϧΫΠϯαʔτ

Slide 51

Slide 51 text

rails db:seed࣮ߦ % rails db:migrate:reset

Slide 52

Slide 52 text

rails db:seed࣮ߦ % rails db:migrate:reset Dropped database …… Created database …… ……

Slide 53

Slide 53 text

rails db:seed࣮ߦ % rails db:migrate:reset Dropped database …… Created database …… …… % rails db:seed

Slide 54

Slide 54 text

rails db:seed࣮ߦ % rails db:migrate:reset Dropped database …… Created database …… …… % rails db:seed "Finished inserting 2 records into books table!” όϧΫΠϯαʔτ׬ྃ💪

Slide 55

Slide 55 text

rails db:seed࣮ߦ % rails db:migrate:reset Dropped database …… Created database …… …… % rails db:seed "Finished inserting 2 records into books table!” % rails s όϧΫΠϯαʔτ׬ྃ💪

Slide 56

Slide 56 text

rails db:seed࣮ߦ % rails db:migrate:reset Dropped database …… Created database …… …… % rails db:seed "Finished inserting 2 records into books table!” % rails s όϧΫΠϯαʔτ׬ྃ💪

Slide 57

Slide 57 text

׬੒ʁ🤔

Slide 58

Slide 58 text

࣮ӡ༻ΞϓϦͰ ࣮ફ‼ % rails generate_csv_from_db

Slide 59

Slide 59 text

࣮ӡ༻ΞϓϦͰ ࣮ફ‼ % rails generate_csv_from_db "Finished generating db/fixtures/……(3 rows) from DB!” "Finished generating db/fixtures/……(107 rows) from DB!” "Finished generating db/fixtures/……(24 rows) from DB!” "Finished generating db/fixtures/……(8 rows) from DB!” "Finished generating db/fixtures/……(71 rows) from DB!” …… "Total row count: 3113"

Slide 60

Slide 60 text

࣮ӡ༻ΞϓϦͰ ࣮ફ‼ % rails generate_csv_from_db "Finished generating db/fixtures/……(3 rows) from DB!” "Finished generating db/fixtures/……(107 rows) from DB!” "Finished generating db/fixtures/……(24 rows) from DB!” "Finished generating db/fixtures/……(8 rows) from DB!” "Finished generating db/fixtures/……(71 rows) from DB!” …… "Total row count: 3113" CSVͷੜ੒͸׬ྃ👍

Slide 61

Slide 61 text

࣮ӡ༻ΞϓϦͰ ࣮ફ‼ % rails db:migrate:reset Dropped database …… Created database …… ……

Slide 62

Slide 62 text

࣮ӡ༻ΞϓϦͰ ࣮ફ‼ % rails db:migrate:reset Dropped database …… Created database …… …… % rails db:seed

Slide 63

Slide 63 text

࣮ӡ༻ΞϓϦͰ ࣮ફ‼ % rails db:migrate:reset Dropped database …… Created database …… …… % rails db:seed rails aborted! ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: insert or update on table "appointments" violates foreign key constraint "fk_rails_4fdc466d95" DETAIL: Key (branch_id)=(8) is not present in table "branches".

Slide 64

Slide 64 text

࣮ӡ༻ΞϓϦͰ ࣮ફ‼ % rails db:migrate:reset Dropped database …… Created database …… …… % rails db:seed rails aborted! ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: insert or update on table "appointments" violates foreign key constraint "fk_rails_4fdc466d95" DETAIL: Key (branch_id)=(8) is not present in table "branches". class Appointment < ApplicationRecord belongs_to :branch …… end ਌ςʔϒϧΛઌʹ Insert͢Δඞཁ͕͋Δ

Slide 65

Slide 65 text

schema.rbͱᛀΊͬ͜͢Δʁ🤔

Slide 66

Slide 66 text

# db/seeds.rb require 'csv' file_paths = Dir.glob('db/fixtures/bulk_insert/*.csv') previous_path = '' until file_paths.empty? do file_path = file_paths.shift csv = CSV.table(file_path) next if csv.size.zero? begin ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize model.insert_all! csv.map(&:to_hash) table_name = model.table_name p "Finished inserting #{csv.size} records into #{table_name} table!" end rescue ActiveRecord::InvalidForeignKey => e ActiveRecord::Base.connection.execute 'ROLLBACK' if file_path != previous_path p "Inserting #{file_path} failed due to #{e.message}." p "Therefore, it is pushed to the end of file_paths to avoid the error." file_paths << file_path else p "Inserting #{file_path} failed twice in a row. **Inserting #{file_path} was SKIPPED.**" end end previous_path = file_path end

Slide 67

Slide 67 text

࣮ӡ༻ΞϓϦͰ ࣮ફ‼ % rails db:migrate:reset Dropped database …… Created database …… …… % rails db:seed

Slide 68

Slide 68 text

࣮ӡ༻ΞϓϦͰ ࣮ફ‼ % rails db:migrate:reset Dropped database …… Created database …… …… % rails db:seed "Inserting db/fixtures/bulk_insert/Appointment.csv failed due to PG::ForeignKeyViolation: ERROR: insert or update on table \"appointments\" violates foreign key constraint \"fk_rails_4fdc466d95\"\nDETAIL: Key (branch_id)=(8) is not present in table \"branches\".\n." "Therefore, it is pushed to the end of file_paths to avoid the error.”

Slide 69

Slide 69 text

࣮ӡ༻ΞϓϦͰ ࣮ફ‼ % rails db:migrate:reset Dropped database …… Created database …… …… % rails db:seed "Inserting db/fixtures/bulk_insert/Appointment.csv failed due to PG::ForeignKeyViolation: ERROR: insert or update on table \"appointments\" violates foreign key constraint \"fk_rails_4fdc466d95\"\nDETAIL: Key (branch_id)=(8) is not present in table \"branches\".\n." "Therefore, it is pushed to the end of file_paths to avoid the error.” …… "Finished inserting 11 records into branches table!”

Slide 70

Slide 70 text

࣮ӡ༻ΞϓϦͰ ࣮ફ‼ % rails db:migrate:reset Dropped database …… Created database …… …… % rails db:seed "Inserting db/fixtures/bulk_insert/Appointment.csv failed due to PG::ForeignKeyViolation: ERROR: insert or update on table \"appointments\" violates foreign key constraint \"fk_rails_4fdc466d95\"\nDETAIL: Key (branch_id)=(8) is not present in table \"branches\".\n." "Therefore, it is pushed to the end of file_paths to avoid the error.” …… "Finished inserting 11 records into branches table!” …… "Finished inserting 2 records into appointments table!” Insert΋ແࣄ׬ྃ😉

Slide 71

Slide 71 text

# db/seeds.rb require 'csv' dir = 'db/fixtures/bulk_insert/*.csv' order_txt = 'db/fixtures/bulk_insert/file_paths_order.txt' def correct_order_exist?(order_txt, dir) File.exist?(order_txt) && File.open(order_txt, 'r').read.split("\n").sort == Dir.glob(dir).sort end file_paths = correct_order_exist?(order_txt, dir) ? File.open(order_txt, 'r').read.split("\n") : Dir.glob(dir) previous_path = '' inserted_file_paths = [] until file_paths.empty? do file_path = file_paths.shift csv = CSV.table(file_path) next if csv.size.zero? begin ActiveRecord::Base.transaction do …… inserted_file_paths << file_path end …… end File.open(order_txt, 'w') do |file| file.write(inserted_file_paths.join("\n")) p "Finished generating #{order_txt} for future seeding!" end

Slide 72

Slide 72 text

# db/seeds.rb require 'csv' dir = 'db/fixtures/bulk_insert/*.csv' order_txt = 'db/fixtures/bulk_insert/file_paths_order.txt' def correct_order_exist?(order_txt, dir) File.exist?(order_txt) && File.open(order_txt, 'r').read.split("\n").sort == Dir.glob(dir).sort end file_paths = correct_order_exist?(order_txt, dir) ? File.open(order_txt, 'r').read.split("\n") : Dir.glob(dir) previous_path = '' inserted_file_paths = [] until file_paths.empty? do file_path = file_paths.shift csv = CSV.table(file_path) next if csv.size.zero? begin ActiveRecord::Base.transaction do …… inserted_file_paths << file_path end …… end File.open(order_txt, 'w') do |file| file.write(inserted_file_paths.join("\n")) p "Finished generating #{order_txt} for future seeding!" end ←

Slide 73

Slide 73 text

# db/seeds.rb require 'csv' dir = 'db/fixtures/bulk_insert/*.csv' order_txt = 'db/fixtures/bulk_insert/file_paths_order.txt' def correct_order_exist?(order_txt, dir) File.exist?(order_txt) && File.open(order_txt, 'r').read.split("\n").sort == Dir.glob(dir).sort end file_paths = correct_order_exist?(order_txt, dir) ? File.open(order_txt, 'r').read.split("\n") : Dir.glob(dir) previous_path = '' inserted_file_paths = [] until file_paths.empty? do file_path = file_paths.shift csv = CSV.table(file_path) next if csv.size.zero? begin ActiveRecord::Base.transaction do …… inserted_file_paths << file_path end …… end File.open(order_txt, 'w') do |file| file.write(inserted_file_paths.join("\n")) p "Finished generating #{order_txt} for future seeding!" end

Slide 74

Slide 74 text

Seed׬ྃʂ

Slide 75

Slide 75 text

ελοϑ༻ը໘ Insert͞Ε͍ͯΔ👍

Slide 76

Slide 76 text

ελοϑ༻ը໘ ৽نϨίʔυͷอଘ

Slide 77

Slide 77 text

ελοϑ༻ը໘ Τϥʔൃੜ😥

Slide 78

Slide 78 text

ΤϥʔͷݪҼ CSVʹidΛؚΊ͍ͯΔ͜ͱ

Slide 79

Slide 79 text

ΤϥʔͷݪҼ CSVʹidΛؚΊ͍ͯΔ͜ͱ

Slide 80

Slide 80 text

ΤϥʔͷݪҼ CSVʹidΛؚΊ͍ͯΔ͜ͱ ໌ࣔతʹࢦఆͨ͜͠ͱͰɺ γʔέϯεΦϒδΣΫτ͕ਖ਼ৗʹߋ৽͞Εͣ ←

Slide 81

Slide 81 text

ղܾํ๏ ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize model.insert_all! csv.map(&:to_hash) table_name = model.table_name sql = "SELECT SETVAL ('#{table_name}_id_seq', (SELECT MAX(id) FROM #{table_name}))" ActiveRecord::Base.connection.execute(sql) p "Finished inserting #{csv.size} records into #{table_name} table!" inserted_file_paths << file_path end γʔέϯεΦϒδΣΫτΛ खಈͰमਖ਼͢Δ ໌ࣔతʹࢦఆͨ͜͠ͱͰɺ γʔέϯεΦϒδΣΫτ͕ਖ਼ৗʹߋ৽͞Εͣ ←

Slide 82

Slide 82 text

ղܾํ๏ ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize model.insert_all! csv.map(&:to_hash) table_name = model.table_name sql = "SELECT SETVAL ('#{table_name}_id_seq', (SELECT MAX(id) FROM #{table_name}))" ActiveRecord::Base.connection.execute(sql) p "Finished inserting #{csv.size} records into #{table_name} table!" inserted_file_paths << file_path end γʔέϯεΦϒδΣΫτΛ खಈͰमਖ਼͢Δ ໌ࣔతʹࢦఆͨ͜͠ͱͰɺ γʔέϯεΦϒδΣΫτ͕ਖ਼ৗʹߋ৽͞Εͣ ← (PostgreSQLͷ৔߹)

Slide 83

Slide 83 text

΋͏Ұ౓ొ࿥ % rails db:migrate:reset % rails db:seed % rails s

Slide 84

Slide 84 text

΋͏Ұ౓ొ࿥ % rails db:migrate:reset % rails db:seed % rails s

Slide 85

Slide 85 text

΋͏Ұ౓ొ࿥ ແࣄʹ`id: 3`Ͱొ࿥׬ྃ🙌 % rails db:migrate:reset % rails db:seed % rails s % rails c irb(main):001> Appointment.last => #

Slide 86

Slide 86 text

ࠓ౓ͦ͜׬੒ͩΖ͏😊

Slide 87

Slide 87 text

࣍ͷ೔☀

Slide 88

Slide 88 text

Seed͠௚ͦ͏͔ͳʙ

Slide 89

Slide 89 text

࠶Seedޙͷը໘

Slide 90

Slide 90 text

࠶Seedޙͷը໘ Appointment͕ ແ͘ͳ͍ͬͯΔ😰

Slide 91

Slide 91 text

࠶Seedޙͷը໘ τοϓϖʔδ͸ຊ೔ͷ೔෇

Slide 92

Slide 92 text

࠶Seedޙͷը໘ 1೔લͷϖʔδʹ͋ͬͨ😥 1೔લͷ༧ఆཝ

Slide 93

Slide 93 text

Appointmentʹ ଘࡏ͢ΔΧϥϜ starts_at: ։࢝೔࣌ ends_at: ऴྃ೔࣌

Slide 94

Slide 94 text

Appointmentʹ ଘࡏ͢ΔΧϥϜ starts_at: ։࢝೔࣌ ends_at: ऴྃ೔࣌ Seedޙʹτοϓϖʔδʹ Appointment͕1ͭදࣔ͞Εͯ΄͍͠ ←

Slide 95

Slide 95 text

Seed࣌ʹɺCSV࡞੒೔ͱͷ ࠩ෼Λௐ੔͢Ε͹͍͚ͦ͏

Slide 96

Slide 96 text

# lib/tasks/generate_csv_from_db.rake require 'csv' desc 'for generating csv from db' task :generate_csv_from_db => :environment do |_task, args| def generate_csv(model_name) …… end total_count = 0 ActiveRecord::Base.connection .tables .reject{ |t| t.in? %w(schema_migrations ar_internal_metadata) } .each { |t| total_count += generate_csv(t.classify) } p "Total row count: #{total_count}" File.open("db/fixtures/bulk_insert/generated_date.txt", 'w') do |file| generated_date = Time.current.to_s file.write(generated_date) p "Saved generated_date: #{generated_date} to db/fixtures/bulk_insert/generated_date.txt!" end end CSVʹશϨίʔυग़ྗ ←

Slide 97

Slide 97 text

# db/seeds.rb require 'csv' def offset_dates(hash, generated_before) hash[:starts_at] = hash[:starts_at].to_time + generated_before if hash[:starts_at].present? hash[:ends_at] = hash[:ends_at].to_time + generated_before if hash[:ends_at].present? hash end …… generated_date_txt = 'db/fixtures/bulk_insert/generated_date.txt' ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize generated_date = File.open(generated_date_txt, 'r').read generated_before = (Time.current.to_date - generated_date.to_date).to_i.days model.insert_all! csv.map(&:to_hash).map { |hash| offset_dates(hash, generated_before) } table_name = model.table_name sql = "SELECT SETVAL ('#{table_name}_id_seq', (SELECT MAX(id) FROM #{table_name}))" ActiveRecord::Base.connection.execute(sql) p "Finished inserting #{csv.size} records into #{table_name} table!" inserted_file_paths << file_path end ……

Slide 98

Slide 98 text

# db/seeds.rb require 'csv' def offset_dates(hash, generated_before) hash[:starts_at] = hash[:starts_at].to_time + generated_before if hash[:starts_at].present? hash[:ends_at] = hash[:ends_at].to_time + generated_before if hash[:ends_at].present? hash end …… generated_date_txt = 'db/fixtures/bulk_insert/generated_date.txt' ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize generated_date = File.open(generated_date_txt, 'r').read generated_before = (Time.current.to_date - generated_date.to_date).to_i.days model.insert_all! csv.map(&:to_hash).map { |hash| offset_dates(hash, generated_before) } table_name = model.table_name sql = "SELECT SETVAL ('#{table_name}_id_seq', (SELECT MAX(id) FROM #{table_name}))" ActiveRecord::Base.connection.execute(sql) p "Finished inserting #{csv.size} records into #{table_name} table!" inserted_file_paths << file_path end ……

Slide 99

Slide 99 text

# db/seeds.rb require 'csv' def offset_dates(hash, generated_before) hash[:starts_at] = hash[:starts_at].to_time + generated_before if hash[:starts_at].present? hash[:ends_at] = hash[:ends_at].to_time + generated_before if hash[:ends_at].present? hash end …… generated_date_txt = 'db/fixtures/bulk_insert/generated_date.txt' ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize generated_date = File.open(generated_date_txt, 'r').read generated_before = (Time.current.to_date - generated_date.to_date).to_i.days model.insert_all! csv.map(&:to_hash).map { |hash| offset_dates(hash, generated_before) } table_name = model.table_name sql = "SELECT SETVAL ('#{table_name}_id_seq', (SELECT MAX(id) FROM #{table_name}))" ActiveRecord::Base.connection.execute(sql) p "Finished inserting #{csv.size} records into #{table_name} table!" inserted_file_paths << file_path end …… 1 day ←

Slide 100

Slide 100 text

# db/seeds.rb require 'csv' def offset_dates(hash, generated_before) hash[:starts_at] = hash[:starts_at].to_time + generated_before if hash[:starts_at].present? hash[:ends_at] = hash[:ends_at].to_time + generated_before if hash[:ends_at].present? hash end …… generated_date_txt = 'db/fixtures/bulk_insert/generated_date.txt' ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize generated_date = File.open(generated_date_txt, 'r').read generated_before = (Time.current.to_date - generated_date.to_date).to_i.days model.insert_all! csv.map(&:to_hash).map { |hash| offset_dates(hash, generated_before) } table_name = model.table_name sql = "SELECT SETVAL ('#{table_name}_id_seq', (SELECT MAX(id) FROM #{table_name}))" ActiveRecord::Base.connection.execute(sql) p "Finished inserting #{csv.size} records into #{table_name} table!" inserted_file_paths << file_path end …… 1 day ←

Slide 101

Slide 101 text

# db/seeds.rb require 'csv' def offset_dates(hash, generated_before) hash[:starts_at] = hash[:starts_at].to_time + generated_before if hash[:starts_at].present? hash[:ends_at] = hash[:ends_at].to_time + generated_before if hash[:ends_at].present? hash end …… generated_date_txt = 'db/fixtures/bulk_insert/generated_date.txt' ActiveRecord::Base.transaction do model = File.basename(file_path, '.csv').constantize generated_date = File.open(generated_date_txt, 'r').read generated_before = (Time.current.to_date - generated_date.to_date).to_i.days model.insert_all! csv.map(&:to_hash).map { |hash| offset_dates(hash, generated_before) } table_name = model.table_name sql = "SELECT SETVAL ('#{table_name}_id_seq', (SELECT MAX(id) FROM #{table_name}))" ActiveRecord::Base.connection.execute(sql) p "Finished inserting #{csv.size} records into #{table_name} table!" inserted_file_paths << file_path end ……

Slide 102

Slide 102 text

೔෇ࠩ෼Λௐ੔ޙ Seed͠ͳ͓͠ % rails db:migrate:reset % rails db:seed % rails s

Slide 103

Slide 103 text

೔෇ࠩ෼Λௐ੔ޙ Seed͠ͳ͓͠ τοϓϖʔδʹ Appointment͋Γ👍 % rails db:migrate:reset % rails db:seed % rails s

Slide 104

Slide 104 text

ຊ౰ʹ׬੒🥳

Slide 105

Slide 105 text

🎊ແࣄʹϚʔδ͞Ε·ͨ͠🎊

Slide 106

Slide 106 text

ϝϯςφϯε΋͔ΜͨΜʂ

Slide 107

Slide 107 text

Seed͠ͳ͓͠ ↓ ϩʔΧϧͷσʔλΛमਖ਼ ↓ generate_csv͢Δ

Slide 108

Slide 108 text

SeedσʔλΛ৽ͨʹ਺ेߦ௥Ճͨ࣌͠ͷPull Request

Slide 109

Slide 109 text

SeedσʔλΛ৽ͨʹ਺ेߦ௥Ճͨ࣌͠ͷPull Request ⁉

Slide 110

Slide 110 text

೔෇Λoffsetͨ͠ΧϥϜʹຖճdiff͕ൃੜͯ͠͠·͏

Slide 111

Slide 111 text

seeds.rbΛॻ͔ͳ͍ํ๏ͷ·ͱΊ • seeds.rbΛͨ͘͞Μॻ͍ͨ😂(ΤϯδχΞ͋Δ͋Δ) • γʔέϯεΦϒδΣΫτɺ೔෇ܥΧϥϜͷௐ੔ͳͲΠϨΪϡϥʔͳରԠ͕ 
 ͍͔ͭ͘ඞཁ(ಛʹ೔෇ͷௐ੔͸ɺΞϓϦͷ࢓༷ʹΑΔͱࢥΘΕΔ) • ຖճseeds.rbΛॻ͔ͳ͍͍ͯ͘ͷ͸շద🥳 
 ಋೖલ: ໿40/100Ϟσϧɺ߹ܭ50,000Ϩίʔυఔ౓ɺSeed࣮ߦʹ30ඵఔ౓ 
 ಋೖޙ: ໿90/100Ϟσϧɺ߹ܭ3,000Ϩίʔυఔ౓ɺSeed࣮ߦʹ5ඵఔ౓ 
 →࣮ࡍͷΞϓϦͷ࢖ΘΕํΛ૝ఆɺಈ࡞֬ೝ΍ෆ۩߹ݕূʹ໾ཱ͍ͬͯΔ

Slide 112

Slide 112 text

͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ