Skip to content

Instantly share code, notes, and snippets.

@hernan
Forked from axehomeyg/sqlite_test_db_loader.rb
Created February 24, 2022 02:39
Show Gist options
  • Select an option

  • Save hernan/f384a2ad52d9544faa39fe5f340d491a to your computer and use it in GitHub Desktop.

Select an option

Save hernan/f384a2ad52d9544faa39fe5f340d491a to your computer and use it in GitHub Desktop.

Revisions

  1. @axehomeyg axehomeyg created this gist Dec 9, 2019.
    83 changes: 83 additions & 0 deletions sqlite_test_db_loader.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,83 @@
    #### evals the schema into the current process
    class SqliteTestDbLoader

    # assumes your schema is generated for MySQL
    # tweak for Postgres!
    MYSQL_REPLACEMENTS = {
    /ENGINE=InnoDB DEFAULT CHARSET=[a-z0-9]*/ => '',
    /, collation: "[^"]*"/ => ''
    }

    class << self
    def reload!(context)
    new.reload!
    ensure
    # puts "Reloaded Schema: #{context}"
    end
    end

    # grab schema from fs
    def extract
    File.read(
    Rails.root.join(
    "db", "schema.rb"))
    end

    # Get rid of non-standard SQL unimportables
    def transform(schema)
    MYSQL_REPLACEMENTS
    .reduce(schema) do |res, replacement|
    res.gsub(*replacement)
    end
    end

    # load into sqlite's :memory: db
    def load(schema)
    eval(schema)
    end

    def reload! ; load(transform(extract)) ; end
    end

    # Always load schema into :memory: after a new connection
    module SqlitePostConnectionLoad
    def establish_connection(*args, &block)
    super
    connection
    .migration_context
    .needs_migration? &&
    SqliteTestDbLoader.reload!("#{self.class.name}#establish_connection")
    end
    end

    # "rails/test_help" needs a connection early on in the test_helper load process
    module CheckPendingSoftly
    def check_pending!(conn = ActiveRecord::Base.connection)
    conn
    .migration_context
    .needs_migration?
    .yield_self do |needs_migration|
    needs_migration &&
    SqliteTestDbLoader.reload!("#{self.class.name}#check_pending!")
    end
    end
    end

    module PreserveParallelMemoryDatabase
    def create_and_load_schema(i, env_name:)
    if ActiveRecord::Base
    .configurations
    .configs_for(env_name: env_name)
    .to_s.match(/:memory:/m)
    puts "Memory database found. Skipping db creation"
    ActiveRecord::Base.establish_connection(Rails.env.to_sym)
    return
    end
    super
    end
    end

    ActiveSupport.on_load(:active_record) do
    ActiveRecord::Migration.singleton_class.prepend CheckPendingSoftly
    ActiveRecord::TestDatabases.singleton_class.prepend PreserveParallelMemoryDatabase
    end
    34 changes: 34 additions & 0 deletions test_helper.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,34 @@
    ENV['RAILS_ENV'] ||= 'test'
    require_relative '../config/environment'

    # must load BEFORE rails/test_help
    require_relative './support/sqlite_test_db_loader.rb'
    require 'rails/test_help'
    require "minitest/rails"

    # This assumes you're sharing config between unit/integration
    module TestSetup
    extend ActiveSupport::Concern

    included do
    # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
    fixtures :all

    # Use Jest-like CI flag
    parallelize(workers: ENV['CI'] ? 1 : :number_of_processors, with: :processes)

    # Make sure that you reload the sqlite when starting processes
    parallelize_setup do
    # slightly more efficient than a direct call to establish_connection
    ActiveRecord::Migration.check_pending!
    end
    end
    end

    class ActiveSupport::TestCase
    include TestSetup
    end

    class ActionDispatch::IntegrationTest
    include TestSetup
    end