Skip to content

Factory bot migration#5121

Draft
philippthun wants to merge 2 commits into
cloudfoundry:mainfrom
sap-contributions:factory-bot-migration
Draft

Factory bot migration#5121
philippthun wants to merge 2 commits into
cloudfoundry:mainfrom
sap-contributions:factory-bot-migration

Conversation

@philippthun
Copy link
Copy Markdown
Member

Thanks for contributing to cloud_controller_ng. To speed up the process of reviewing your pull request please provide us with:

  • A short explanation of the proposed change:

  • An explanation of the use cases your change solves

  • Links to any other associated PRs

  • I have reviewed the contributing guide

  • I have viewed, signed, and submitted the Contributor License Agreement

  • I have made this pull request to the main branch

  • I have run all the unit tests using bundle exec rake

  • I have run CF Acceptance Tests

ADR 0002 (2019) chose to keep machinist after a partial factory_bot
migration hit friction with Sequel's mutual-foreign-key pattern.

The blocker described there is solvable in factory_bot using a global
to_create with save+refresh and after(:create) callbacks with transient
flags. machinist 1.0.6 has had no upstream activity since 2013, and 2.0
is not a viable upgrade (no Sequel adapter, no Sham, non-persisting
make).

Mark ADR 0002 as superseded and add ADR 0015 documenting the new
decision and the patterns that made it work.
Per ADR 0015. machinist 1.0.6 has had no upstream activity since 2013
and machinist 2.0 is not a viable upgrade (no Sequel adapter, no Sham,
non-persisting make). FactoryBot is actively maintained, has trivial
Sequel integration, and provides equivalents for every pattern used
by the existing blueprints.

Convert ~11k call sites from Model.make / Model.make_unsaved to
create(:foo) / build(:foo), replace ~130 blueprints with factory
definitions under spec/support/factory_definitions/, and remove the
machinist gem along with spec/support/fakes/blueprints.rb and
spec/support/machinist_monkey_patch.rb.

Key technical decisions (see ADR 0015):

- Global to_create { |i| i.save; i.refresh } in
  spec/support/factories.rb. This matches machinist's Sequel adapter
  which both saved and refreshed; the refresh prevents stale-cache
  bugs whenever a factory's after-create hook mutates associations.

- Sham is preserved as a thin shim (spec/support/sham_shim.rb) that
  delegates Sham.<name> to FactoryBot.generate(:sham_<name>) sequences
  defined in spec/support/factories.rb. The shim mirrors the original
  Sham.define block 1:1 so existing call sites need no edits.

- Dynamic class -> factory-name conversion via
  klass.name.demodulize.underscore.to_sym is used in matchers and
  shared examples, so generic helpers continue to look up the right
  factory when given any model class.

- Named blueprints become traits: Foo.blueprint(:bar) turns into a
  trait :bar on the :foo factory; Foo.make(:bar, x: 1) becomes
  create(:foo, :bar, x: 1).

- build replaces make_unsaved for the (rare) cases that wanted an
  unsaved instance.

- :droplet_model only auto-sets itself as the app's current droplet
  when no app: override is supplied (set_as_current_droplet
  { app == :unset }), matching machinist's blueprint where the default
  app block only ran in that case. Specs that previously relied on the
  auto-set side effect when passing app: explicitly call
  app.update(droplet:) just as the pre-migration versions did.

- :revision_sidecar_process_type_model builds its parent with the
  :no_process_types trait so FactoryBot.lint does not collide with the
  parent's after-create web row on the (revision_sidecar_guid, type)
  unique constraint.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant