Skip to content

Instantly share code, notes, and snippets.

@ram-ai-kumar
Last active January 16, 2024 09:37
Show Gist options
  • Select an option

  • Save ram-ai-kumar/e3ae6ac269ca7a28bb2ee21eed824e91 to your computer and use it in GitHub Desktop.

Select an option

Save ram-ai-kumar/e3ae6ac269ca7a28bb2ee21eed824e91 to your computer and use it in GitHub Desktop.
Resilient, faster and maintainable seeding in ruby on rails
# 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
# 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
# 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