Last active
January 16, 2024 09:37
-
-
Save ram-ai-kumar/e3ae6ac269ca7a28bb2ee21eed824e91 to your computer and use it in GitHub Desktop.
Resilient, faster and maintainable seeding in ruby on rails
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # frozen_string_literal: true | |
| # a simple user factory | |
| # factories/users.rb | |
| # | |
| FactoryBot.define do | |
| factory :user do | |
| name { Faker::Name.unique.name } | |
| email { Faker::Internet.email(domain: "bharat.in") } | |
| # some users will randomly be "admin" | |
| role { "admin" } if [true, false].sample | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # frozen_string_literal: true | |
| # This file should ensure the existence of records required to run the application in every environment (production, | |
| # development, test). The code here should be idempotent so that it can be executed at any point in every environment. | |
| # The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). | |
| # | |
| # Example: | |
| # | |
| # ["Action", "Comedy", "Drama", "Horror"].each do |genre_name| | |
| # MovieGenre.find_or_create_by!(name: genre_name) | |
| # end | |
| # fail-fast with guard-clause | |
| # | |
| return if Rails.env.production? | |
| # | |
| # start seeding when not in production | |
| # | |
| require "factory_bot" | |
| require_relative "seeds/helper" | |
| # seed constants | |
| seeds = { | |
| users: 5, | |
| devices: 10, | |
| alarms: 10, | |
| messages: 10, | |
| video_calls: 20, | |
| groups: 5 | |
| } | |
| # start a block that will reset the logger on any error | |
| # | |
| begin | |
| # seeds/helper.rb | |
| # set the logger to what we need for the current environment | |
| # | |
| _logger = set_logger | |
| log_and_run "Seeding the database..." | |
| # Users, that will be Admins | |
| # | |
| # delete existing | |
| log_and_run("Removing existing users...") { User.delete_all } | |
| # creates a randomly sized array of hashes, filled with attributes from factory | |
| # add them together with a single call | |
| users = Array.new(rand(1..seeds[:users])) { FactoryBot.attributes_for(:user) } | |
| User.insert_all(users) | |
| # add at least one known admin | |
| FactoryBot.create(:user, | |
| role: "admin", | |
| name: "Admin", email: "admin@bharat.in", | |
| password: "password", password_confirmation: "password") | |
| # log the result | |
| log_and_run "Added #{users.length + 1} users: #{users.first(5).pluck(:email).join(", ")}..." | |
| # rescue from any exception as StandardError | |
| # we need this to reset the logger back to original | |
| # | |
| rescue => e | |
| # | |
| # switch the logger back to what was earlier | |
| reset_logger | |
| # | |
| # raise the exception again to get rescued in the call chain | |
| raise e | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # frozen_string_literal: true | |
| # | |
| # helper methods for seeding | |
| # seeds/helper.rb | |
| # | |
| # | |
| # Log and Run the block | |
| # | |
| # @param [String] message to log in the currently set logger | |
| # [Block] block to yield | |
| # | |
| def log_and_run(message = ".") | |
| Rails.logger.info message.to_s | |
| yield if block_given? | |
| end | |
| # | |
| # switch the logger to $stdout and use `logger.info` for status updates | |
| # | |
| # @return [Object] Logger object that we have set | |
| # | |
| def set_logger | |
| @pre_seed_logger = Rails.logger | |
| Rails.logger = Logger.new($stdout) | |
| end | |
| # | |
| # Reset the logger back to what it was before seeding | |
| # | |
| def reset_logger | |
| Rails.logger = @pre_seed_logger | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment