diff --git a/README.md b/README.md index a119108..e6ba9d7 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,17 @@ class MyEngine < ::Rails::Engine end ``` +If your application has a large number of factories, you may want to enable +lazy loading to speed up boot time: + +```rb +config.factory_bot.lazy_load_definitions = true +``` + +With lazy loading of definitions enabled, `FactoryBot.factories` will appear +empty after booting the application. All factory definitions will be loaded +when any factory is first accessed by name. + You can also disable automatic factory definition loading entirely by using an empty array: diff --git a/features/load_definitions.feature b/features/load_definitions.feature index 4c01b9c..6c064f7 100644 --- a/features/load_definitions.feature +++ b/features/load_definitions.feature @@ -197,3 +197,36 @@ Feature: automatically load factory definitions """ When I run `bundle exec rake test` with a clean environment Then the output should contain "2 assertions, 0 failures, 0 errors" + + Scenario: use lazy loading of factory definitions + When I configure the factories as: + """ + config.factory_bot.lazy_load_definitions = true + """ + When I write to "test/factories.rb" with: + """ + FactoryBot.define do + factory :user do + name { "Frank" } + end + end + """ + When I write to "test/unit/user_test.rb" with: + """ + require 'test_helper' + + class UserTest < ActiveSupport::TestCase + test "use lazy loaded factory" do + assert FactoryBot.factories.none? + refute FactoryBot.factories.registered?(:user) + + user = FactoryBot.build(:user) + assert_equal 'Frank', user.name + + assert FactoryBot.factories.any? + assert FactoryBot.factories.registered?(:user) + end + end + """ + When I run `bundle exec rake test` with a clean environment + Then the output should contain "5 assertions, 0 failures, 0 errors" diff --git a/lib/factory_bot_rails/lazy_registry_find.rb b/lib/factory_bot_rails/lazy_registry_find.rb new file mode 100644 index 0000000..033eceb --- /dev/null +++ b/lib/factory_bot_rails/lazy_registry_find.rb @@ -0,0 +1,16 @@ +require "factory_bot/registry" + +module FactoryBotRails + module LazyRegistryFind + def self.find_definitions_once + return if defined?(@definitions_loaded) + FactoryBot.find_definitions + @definitions_loaded = true + end + + def find(*) + LazyRegistryFind.find_definitions_once + super + end + end +end diff --git a/lib/factory_bot_rails/railtie.rb b/lib/factory_bot_rails/railtie.rb index 2b12237..b106fa7 100644 --- a/lib/factory_bot_rails/railtie.rb +++ b/lib/factory_bot_rails/railtie.rb @@ -11,6 +11,7 @@ module FactoryBotRails class Railtie < Rails::Railtie config.factory_bot = ActiveSupport::OrderedOptions.new config.factory_bot.definition_file_paths = FactoryBot.definition_file_paths + config.factory_bot.lazy_load_definitions = false config.factory_bot.validator = FactoryBotRails::FactoryValidator.new config.factory_bot.file_fixture_support = true @@ -39,7 +40,13 @@ class Railtie < Rails::Railtie end config.after_initialize do |app| - FactoryBot.find_definitions + if app.config.factory_bot.lazy_load_definitions && !app.config.eager_load + require "factory_bot_rails/lazy_registry_find" + FactoryBot::Registry.prepend FactoryBotRails::LazyRegistryFind + else + FactoryBot.find_definitions + end + Reloader.new(app).run app.config.factory_bot.validator.run end