Factory Bot 2.4 Goes Meta

Josh Clayton

Factory Bot1 has been getting some hardcore internal refactorings over the past few months. Traits are a great example of something that’s started very bare-bones with a few caveats and been transformed to one of my favorite features of the Factory Bot syntax. It required a pretty decent chunk of refactoring and there were bugs for quite a while due to the way attributes in general were handled.

The Old Way

Internally, Factory Bot has four different types of attributes (Dynamic, Static, Association, and Sequence); when compiling attributes, we were sorting attributes by the order attributes were added, moving all static attributes to the beginning of the list (with a priority attribute). This worked for 99% of all cases but did have bugs (the most recent involved traits and dynamic attributes). I wanted to resolve this once and for all.

The New Way

Factory Bot now creates a new class per factory (with some awesome usage of Class.new) and defines methods on that class for each attribute declared in the factory files. This means Factory Bot doesn’t have to worry about sorting attributes anymore; every attribute is effectively lazily-evaluated so it’ll return the correct value every time. Factory Bot also uses inheritance for these anonymous classes, resulting in a pretty significant speedup of factory interaction (namely because we were copying all parent attributes and callbacks to each child to mimic inheritance before).

What Does It Mean

Factory Bot is now faster!

Here’s some benchmarks from Factory Bot 2.3.0:

                                user     system      total        real
build x10000                4.920000   0.010000   4.930000 (  5.028088)
trait build x10000          6.180000   0.010000   6.190000 (  6.296030)
inline trait build x10000   5.870000   0.010000   5.880000 (  5.989512)
deep build x10000           8.100000   0.020000   8.120000 (  8.285039)
attributes_for x10000       3.200000   0.010000   3.210000 (  3.289043)
create x500                 1.010000   0.320000   1.330000 (  4.186271)

And from Factory Bot 2.4.0:

                                user     system      total        real
build x10000                3.050000   0.000000   3.050000 (  3.121359)
trait build x10000          3.260000   0.010000   3.270000 (  3.353590)
inline trait build x10000   6.700000   0.040000   6.740000 (  7.037460)
deep build x10000           3.400000   0.010000   3.410000 (  3.503984)
attributes_for x10000       0.820000   0.010000   0.830000 (  0.886641)
create x500                 0.710000   0.310000   1.020000 (  3.980102)

Grab a copy of Factory Bot 2.4.0 and speed up your suite!

Project name history can be found here.

  1. Looking for FactoryGirl? The library was renamed in 2017.