$30 off During Our Annual Pro Sale. View Details »

seeds.rbを書かずに開発環境データを整備する

gogutan
October 27, 2023

 seeds.rbを書かずに開発環境データを整備する

gogutan

October 27, 2023
Tweet

More Decks by gogutan

Other Decks in Programming

Transcript

  1. seeds.rbΛॻ͔
    ず
    ʹ


    ։ൃ؀ڥ
    デ
    ʔλΛ੔උ͢Δ
    @gogutan


    Kaigi on Rails 2023 Day1 10.27(Fri.)

    View Slide

  2. ࣗݾ঺հ
    • @gogutan


    • झຯ : ӳޠɺڝϓϩ(AtCoder)ɺ
    ໺ٿ؍ઓ


    • FJORD BOOT CAMPग़਎


    • Tech Lead @ גࣜձࣾΩϟλϧ

    View Slide

  3. Seedσʔλͷϝϯςφϯε


    ͯ͠·͔͢ʁ

    View Slide

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


    View Slide

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


    Book.create!(


    title: 'ֶ໰ͷ͢͢Ί',


    author: '෱୔་٢'


    )


    View Slide

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


    Book.create!(


    title: 'ֶ໰ͷ͢͢Ί',


    author: '෱୔་٢'


    )


    % rails db:seed


    View Slide

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


    Book.create!(


    title: 'ֶ໰ͷ͢͢Ί',


    author: '෱୔་٢'


    )


    % rails db:seed


    % rails c


    View Slide

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


    Book.create!(


    title: 'ֶ໰ͷ͢͢Ί',


    author: '෱୔་٢'


    )


    % rails db:seed


    % rails c


    irb(main):001> Book.first


    View Slide

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


    Book.create!(


    title: 'ֶ໰ͷ͢͢Ί',


    author: '෱୔་٢'


    )


    % rails db:seed


    % rails c


    irb(main):001> Book.first


    =>


    #

    id: 1,


    title: “ֶ໰ͷ͢͢Ί",


    author: "෱୔་٢",


    created_at: Tue, 17 Oct 2023 01:03:26.528993000
    JST +09:00,


    updated_at: Tue, 17 Oct 2023 01:03:26.528993000
    JST +09:00>


    ॳظσʔλΛ؆୯ʹ


    ༻ҙͰ͖ͯخ͍͠😊

    View Slide

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

    View Slide

  11. ྫ͑͹ɺBookʹCommentΛ


    ෇͚Δػೳ͕͋ͬͨ࣌

    View Slide

  12. SeedσʔλʹComment͕ແͯ͘΋


    ͦΕ΄ͲࠔΒͳ͍

    View Slide

  13. Ͱ΋CommentΛຖճ


    खಈͰ࡞͍ͬͯΔΑ͏ͳ…

    View Slide

  14. ෳࡶͳϦϨʔγϣϯ΍ίʔϧόοΫ…


    खΛ෇͚ʹ͍͘͜ͱ΋͋Δ

    View Slide

  15. ݁Ռͱͯ͠ى͜ΓಘΔ͜ͱ
    • ֤ΤϯδχΞ͕ϩʔΧϧ؀ڥʹಠࣗͷσʔλΛੵΈॏͶΔ

    (஌ݟ͕ڞ༗͞Εʹ͘͘ͳΔ)


    • Pull Requestຖͷݕূ؀ڥͷσʔλ͕खബʹͳΔ

    (ಈ࡞֬ೝ΍σʔλͷϦετΞʹ͕͔͔࣌ؒΔ)

    View Slide

  16. ݁Ռͱͯ͠ى͜ΓಘΔ͜ͱ
    • ֤ΤϯδχΞ͕ϩʔΧϧ؀ڥʹಠࣗͷσʔλΛੵΈॏͶΔ

    (஌ݟ͕ڞ༗͞Εʹ͘͘ͳΔ)


    • Pull Requestຖͷݕূ؀ڥͷσʔλ͕खബʹͳΔ

    (ಈ࡞֬ೝ΍σʔλͷϦετΞʹ͕͔͔࣌ؒΔ)


    →νʔϜશମͷ։ൃޮ཰͕མͪΔ🫠

    View Slide

  17. 100ۙ͋͘ΔϞσϧͷ͏ͪɺ


    Seedσʔλ͕ଘࡏ͢Δͷ͸4ׂఔ౓😢

    View Slide

  18. खΛ෇͚Δͷ͕೉ͦ͠͏ͳྫ🤯
    • εέδϡʔϥʔܥͷϞσϧʢຖिͷϨοεϯ೔࣌ͳͲʣ


    • ཤྺ؅ཧܥͷϞσϧʢੜెͷϨϕϧΞοϓͷ؅ཧͳͲʣ


    • ͦͷ࣌఺ͷσʔλΛϋʔυίϐʔ͢ΔܥͷϞσϧ

    ʢϨοεϯͰऔΓ૊ΉΧϦΩϡϥϜͳͲʣ

    View Slide

  19. ࠓϩʔΧϧʹ͋ΔΑ͏ͳσʔλ͕


    ཉ͍͚ͩ͠ͳΜ͚ͩͲͳʙ😌

    View Slide

  20. # 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͍ͯ͠Δ


    ϞσϧΛൃݟ👀

    View Slide

  21. Ͱ͖ΔͷͰ͸ʂʁ🤨

    View Slide

  22. seeds.rbΛॻ͔ͳ͍࡞ઓͷ֓ཁ
    • ϩʔΧϧͰΞϓϦΛૢ࡞͍͍ͯ͠ײ͡ͷσʔλΛ༻ҙ͢Δ


    • CSVϑΝΠϧʹશͯͷϨίʔυΛग़ྗ͢Δ


    • rails db:seed࣌ɺCSVϑΝΠϧΛݩʹόϧΫΠϯαʔτ͢Δ

    View Slide

  23. ࣮ફ👀

    View Slide

  24. seeds.rbΛॻ͔ͳ͍࡞ઓͷ֓ཁ
    • ϩʔΧϧͰΞϓϦΛૢ࡞͍͍ͯ͠ײ͡ͷσʔλΛ༻ҙ͢Δ


    • CSVϑΝΠϧʹશͯͷϨίʔυΛग़ྗ͢Δ


    • rails db:seed࣌ɺCSVϑΝΠϧΛݩʹόϧΫΠϯαʔτ͢Δ

    View Slide

  25. ϩʔΧϧʹ͍͍ײ͡ͷ


    σʔλΛ༻ҙ
    BooksΞϓϦʹ2ߦొ࿥ࡁ

    View Slide

  26. seeds.rbΛॻ͔ͳ͍࡞ઓͷ֓ཁ
    • ϩʔΧϧͰΞϓϦΛૢ࡞͍͍ͯ͠ײ͡ͷσʔλΛ༻ҙ͢Δ


    • CSVϑΝΠϧʹશͯͷϨίʔυΛग़ྗ͢Δ


    • rails db:seed࣌ɺCSVϑΝΠϧΛݩʹόϧΫΠϯαʔτ͢Δ

    View Slide

  27. # 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ʹશϨίʔυग़ྗ

    View Slide

  28. # 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ʹશϨίʔυग़ྗ

    View Slide

  29. # 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ʹશϨίʔυग़ྗ

    View Slide

  30. # 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ʹશϨίʔυग़ྗ

    View Slide

  31. # 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ʹશϨίʔυग़ྗ

    View Slide

  32. # 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ʹશϨίʔυग़ྗ

    View Slide

  33. # 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


    ……

    View Slide

  34. # 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


    ……

    View Slide

  35. # 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


    ……

    View Slide

  36. # 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


    ……

    View Slide

  37. # 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


    ……

    View Slide

  38. rakeλεΫ࣮ߦ
    % rails generate_csv_from_db

    View Slide

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

    View Slide

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

    View Slide

  41. seeds.rbΛॻ͔ͳ͍࡞ઓͷ֓ཁ
    • ϩʔΧϧͰΞϓϦΛૢ࡞͍͍ͯ͠ײ͡ͷσʔλΛ༻ҙ͢Δ


    • CSVϑΝΠϧʹશͯͷϨίʔυΛग़ྗ͢Δ


    • rails db:seed࣌ɺCSVϑΝΠϧΛݩʹόϧΫΠϯαʔτ͢Δ

    View Slide

  42. # 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͔ΒόϧΫΠϯαʔτ

    View Slide

  43. # 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͔ΒόϧΫΠϯαʔτ

    View Slide

  44. # 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͔ΒόϧΫΠϯαʔτ

    View Slide

  45. # 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͔ΒόϧΫΠϯαʔτ

    View Slide

  46. # 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͔ΒόϧΫΠϯαʔτ

    View Slide

  47. # 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͔ΒόϧΫΠϯαʔτ

    View Slide

  48. # 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͔ΒόϧΫΠϯαʔτ

    View Slide

  49. # 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͔ΒόϧΫΠϯαʔτ

    View Slide

  50. # 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͔ΒόϧΫΠϯαʔτ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  57. ׬੒ʁ🤔

    View Slide

  58. ࣮ӡ༻ΞϓϦͰ


    ࣮ફ‼
    % rails generate_csv_from_db

    View Slide

  59. ࣮ӡ༻ΞϓϦͰ


    ࣮ફ‼
    % 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"

    View Slide

  60. ࣮ӡ༻ΞϓϦͰ


    ࣮ફ‼
    % 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ͷੜ੒͸׬ྃ👍

    View Slide

  61. ࣮ӡ༻ΞϓϦͰ


    ࣮ફ‼
    % rails db:migrate:reset
    Dropped database ……
    Created database ……
    ……

    View Slide

  62. ࣮ӡ༻ΞϓϦͰ


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

    View Slide

  63. ࣮ӡ༻ΞϓϦͰ


    ࣮ફ‼
    % 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".

    View Slide

  64. ࣮ӡ༻ΞϓϦͰ


    ࣮ફ‼
    % 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͢Δඞཁ͕͋Δ

    View Slide

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

    View Slide

  66. # 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

    View Slide

  67. ࣮ӡ༻ΞϓϦͰ


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

    View Slide

  68. ࣮ӡ༻ΞϓϦͰ


    ࣮ફ‼
    % 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.”

    View Slide

  69. ࣮ӡ༻ΞϓϦͰ


    ࣮ફ‼
    % 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!”

    View Slide

  70. ࣮ӡ༻ΞϓϦͰ


    ࣮ફ‼
    % 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΋ແࣄ׬ྃ😉

    View Slide

  71. # 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

    View Slide

  72. # 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

    View Slide

  73. # 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

    View Slide

  74. Seed׬ྃʂ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  80. ΤϥʔͷݪҼ
    CSVʹidΛؚΊ͍ͯΔ͜ͱ
    ໌ࣔతʹࢦఆͨ͜͠ͱͰɺ


    γʔέϯεΦϒδΣΫτ͕ਖ਼ৗʹߋ৽͞Εͣ

    View Slide

  81. ղܾํ๏
    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


    γʔέϯεΦϒδΣΫτΛ


    खಈͰमਖ਼͢Δ
    ໌ࣔతʹࢦఆͨ͜͠ͱͰɺ


    γʔέϯεΦϒδΣΫτ͕ਖ਼ৗʹߋ৽͞Εͣ

    View Slide

  82. ղܾํ๏
    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ͷ৔߹)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  86. ࠓ౓ͦ͜׬੒ͩΖ͏😊

    View Slide

  87. ࣍ͷ೔☀

    View Slide

  88. Seed͠௚ͦ͏͔ͳʙ

    View Slide

  89. ࠶Seedޙͷը໘

    View Slide

  90. ࠶Seedޙͷը໘
    Appointment͕


    ແ͘ͳ͍ͬͯΔ😰

    View Slide

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

    View Slide

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

    View Slide

  93. Appointmentʹ


    ଘࡏ͢ΔΧϥϜ
    starts_at: ։࢝೔࣌


    ends_at: ऴྃ೔࣌

    View Slide

  94. Appointmentʹ


    ଘࡏ͢ΔΧϥϜ
    starts_at: ։࢝೔࣌


    ends_at: ऴྃ೔࣌
    Seedޙʹτοϓϖʔδʹ


    Appointment͕1ͭදࣔ͞Εͯ΄͍͠

    View Slide

  95. Seed࣌ʹɺCSV࡞੒೔ͱͷ


    ࠩ෼Λௐ੔͢Ε͹͍͚ͦ͏

    View Slide

  96. # 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ʹશϨίʔυग़ྗ

    View Slide

  97. # 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


    ……


    View Slide

  98. # 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


    ……


    View Slide

  99. # 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

    View Slide

  100. # 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

    View Slide

  101. # 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


    ……


    View Slide

  102. ೔෇ࠩ෼Λௐ੔ޙ


    Seed͠ͳ͓͠
    % rails db:migrate:reset
    % rails db:seed
    % rails s

    View Slide

  103. ೔෇ࠩ෼Λௐ੔ޙ


    Seed͠ͳ͓͠
    τοϓϖʔδʹ


    Appointment͋Γ👍
    % rails db:migrate:reset
    % rails db:seed
    % rails s

    View Slide

  104. ຊ౰ʹ׬੒🥳

    View Slide

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

    View Slide

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

    View Slide

  107. Seed͠ͳ͓͠





    ϩʔΧϧͷσʔλΛमਖ਼





    generate_csv͢Δ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  111. seeds.rbΛॻ͔ͳ͍ํ๏ͷ·ͱΊ
    • seeds.rbΛͨ͘͞Μॻ͍ͨ😂(ΤϯδχΞ͋Δ͋Δ)


    • γʔέϯεΦϒδΣΫτɺ೔෇ܥΧϥϜͷௐ੔ͳͲΠϨΪϡϥʔͳରԠ͕

    ͍͔ͭ͘ඞཁ(ಛʹ೔෇ͷௐ੔͸ɺΞϓϦͷ࢓༷ʹΑΔͱࢥΘΕΔ)


    • ຖճseeds.rbΛॻ͔ͳ͍͍ͯ͘ͷ͸շద🥳

    ಋೖલ: ໿40/100Ϟσϧɺ߹ܭ50,000Ϩίʔυఔ౓ɺSeed࣮ߦʹ30ඵఔ౓

    ಋೖޙ: ໿90/100Ϟσϧɺ߹ܭ3,000Ϩίʔυఔ౓ɺSeed࣮ߦʹ5ඵఔ౓

    →࣮ࡍͷΞϓϦͷ࢖ΘΕํΛ૝ఆɺಈ࡞֬ೝ΍ෆ۩߹ݕূʹ໾ཱ͍ͬͯΔ

    View Slide

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

    View Slide