1
0
Fork 0
mirror of https://github.com/thoughtbot/factory_bot_rails.git synced 2022-11-09 11:49:18 -05:00
thoughtbot--factory_bot_rails/lib/factory_bot_rails/reloader.rb
Daniel Colson 1e55d45bfb Ensure factory_bot only loads after initialization
Fixes #336
Alternate solution to #343

The initialization process looks like this:

Rails runs all of the initializers
1. Run the ["factory_bot.set_factory_paths"][set_factory_paths]
initializer
2. Run the ["factory_bot.register_reloader"][register_reloader]
initializer, which sets up a [prepare callback][]
3. Run the [`:run_prepare_callbacks`][] initializer
4. This triggers the factory_bot [prepare callback][], which causes
factory\_bot to [reload][]

Rails runs `after_initialize` callbacks
1. [I18n initializes]
2. factory\_bot [reloads again][] as described in #334

The double reloading of factory_bot in this initialization is not ideal,
but also shouldn't generally cause any problems on its own.

The problems people are having in #336 come from the fact that
I18n gets set up in an `after_initialize` callback, but factory_bot gets
reloaded before the `after_initialize` callbacks are triggered.
If the `FactoryBot.define` block references any code that uses I18n
translations as it loads, that code will raise an error (references
inside other factory_bot methods, or code that uses I18n translations
inside of methods still works fine, since the whole Rails initialization
process would be complete by the time any of that code runs).

This commit changes step 4 above to avoid reloading factory_bot before
the application has initialized.

[set_factory_paths]: 3815aae2b9/lib/factory_bot_rails/railtie.rb (L17-L19)
[register_reloader]: 3815aae2b9/lib/factory_bot_rails/railtie.rb (L21-L23)
[prepare callback]: https://github.com/thoughtbot/factory_bot_rails/blob/master/lib/factory_bot_rails/reloader.rb#L34-L36
[`:run_prepare_callbacks`]: https://github.com/rails/rails/blob/5-2-stable/railties/lib/rails/application/finisher.rb#L62-L64
[reload]: https://github.com/thoughtbot/factory_bot_rails/blob/master/lib/factory_bot_rails/reloader.rb#L24-L26
[I18n initializes]: 13e2102517/activesupport/lib/active_support/i18n_railtie.rb (L16-L20)
[reloads again]: https://github.com/thoughtbot/factory_bot_rails/blob/master/lib/factory_bot_rails/railtie.rb#L25-L27

Co-authored-by: Danny Garcia <dannygarcia.me@gmail.com>
2019-10-02 18:37:42 -04:00

45 lines
838 B
Ruby

# frozen_string_literal: true
require "factory_bot_rails/definition_file_paths"
module FactoryBotRails
class Reloader
def initialize(app, config)
@app = app
@config = config
@paths = DefinitionFilePaths.new(FactoryBot.definition_file_paths)
end
def run
return unless @paths.any?
register_reloader(build_reloader)
end
private
attr_reader :app, :config
def build_reloader
reloader_class.new(@paths.files, @paths.directories) do
FactoryBot.reload
end
end
def reloader_class
app.config.file_watcher
end
def register_reloader(reloader)
closed_over_app = app
config.to_prepare do
if closed_over_app.initialized?
reloader.execute
end
end
app.reloaders << reloader
end
end
end