Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
33 changes: 33 additions & 0 deletions features/load_definitions.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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"
16 changes: 16 additions & 0 deletions lib/factory_bot_rails/lazy_registry_find.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require "factory_bot/registry"

module FactoryBotRails
module LazyRegistryFind
def self.find_definitions_once
return if defined?(@definitions_loaded)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@quadule 👋 Fellow user of this gem... I like the concept of this PR... but, this concerns me, how does this interface with FactoryBot.reload? Does this caching get cleared on reload?

In other words, do we get a new registry when the configuration is reset in reset_configuration?

FactoryBot.find_definitions
@definitions_loaded = true
end

def find(*)
LazyRegistryFind.find_definitions_once
super
end
end
end
9 changes: 8 additions & 1 deletion lib/factory_bot_rails/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be implemented in the factory_bot gem instead, so I'll open another PR for that if there's any interest here.

else
FactoryBot.find_definitions
end

Reloader.new(app).run
app.config.factory_bot.validator.run
end
Expand Down