Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

version 5.0.0 association creation #314

Closed
chevinbrown opened this issue Feb 1, 2019 · 26 comments
Closed

version 5.0.0 association creation #314

chevinbrown opened this issue Feb 1, 2019 · 26 comments

Comments

@chevinbrown
Copy link

This is honestly probably the way it should work (I'm assuming it's somewhat related d320202#diff-e79a60dc6b85309ae70a6ea8261eaf95R26)

When building a record with an association, the associations are not created first.

Quick example:

FactoryBot.define do
  factory :user do
    association :doggie
  end
end

In ~4.11 build :user would create the doggie association.
In ~5.0.0 build :user does not yet create the association.

Is this expected?

I prefer it b/c it's more explicit, but it does seem to be breaking (if indeed I'm on the right track). Any insights?

@composerinteralia
Copy link
Collaborator

composerinteralia commented Feb 1, 2019

Thanks for opening this issue. This was an intentional change; we changed the default value for use_parent_strategy to true in thoughtbot/factory_bot@d0208ed. It is indeed a breaking a change. I would be curious to know how many failures this caused in your test suite, and how long it took you to figure out what was going on.

@chevinbrown
Copy link
Author

Just a few failures, I discovered/reported/fixed in under an hour, so it's pretty minimal.

Was that change missed in the changelog? We got a dependabot PR today to update us from 4.11 -> 5.0

@composerinteralia
Copy link
Collaborator

https://github.com/thoughtbot/factory_bot/blob/806ec9f6fe071f3576aa28c804bacfc7eefc790e/NEWS#L3

But maybe it didn't show up in the dependabot PR because it is in the factory_bot NEWS file, not factory_bot_rails?

@composerinteralia
Copy link
Collaborator

Let's leave this issue open, since I'm sure others will run into this as well.

Also, I should mention that it is possible to revert to the old behavior by setting FactoryBot.use_parent_strategy = false, but I would love to know if anyone ends up needing to do that. Ideally we could deprecate the old behavior at some point, but I don't want to make it impossible for people to update.

@chevinbrown
Copy link
Author

Yeah, that's probably the reason I missed it.

Thanks for the quick response.

Annecdotally, (not to bikeshed!) I greatly prefer an additional setup step instead of a rails-specific gem...Feel free to email me if there are discussion points I need to understand there.

Maybe I should just throw FactoryBot.find_definitions in my test_hepler.rb 😉

I agree--this "new" behavior is best!

@composerinteralia
Copy link
Collaborator

Annecdotally, (not to bikeshed!) I greatly prefer an additional setup step instead of a rails-specific gem...Feel free to email me if there are discussion points I need to understand there.

factory_bot_rails does include a few extra features beyond automatically loading definitions--mostly notably the generator--but if you are not using those I think using factory_bot and calling FactoryBot.find_definitions yourself is totally reasonable.

@chevinbrown
Copy link
Author

@composerinteralia totes. +1 for your responsiveness. Thanks for factory bot! (and ex_machina!)

@tomhughes
Copy link

So if changing the default back is not the recommended way to resolve issues caused by this change then can I ask what is? I can find documentation explaining how this causes behaviour to change, but not how to adapt tests that need to build objects whose associations have been fully created...

If it helps to have an example then consider https://github.com/openstreetmap/openstreetmap-website/blob/master/test/models/old_node_test.rb#L9 which creates an object and then tests it's validity to check that the validations are working. We don't want to try and save it because it might not be valid (indeed some tests do use invalid objects) but we do need the associated objects to be save or their ids won't be set and validation will fail because of that.

@chevinbrown
Copy link
Author

@tomhughes the most simple case in my experience:

# old
# fails b/c of some nonexistent relationship
build(:old_node, :latitude => 90 * OldNode::SCALE)

# new
build(:old_node, :latitude => 90 * OldNode::SCALE, dependent_association: create(:other_node))

You just have to be more explicit in the setup.

I generally find this to be a better pattern anyway--take more time to do slightly more verbose setup blocks will help serve future me when I come back to the test if it's failing.

@tomhughes
Copy link

Thanks. I went a slightly different way in the end and made the tests check for the validation they are actually interested in which should be more robust - some of them were effectively silently not doing what was intended as a result of this change combined with them being too generic.

@pboling
Copy link

pboling commented Feb 7, 2019

Just for additional context on this issue: The upgrade is breaking a quarter of spec suites according to meta analysis by depend-a-bot
https://dependabot.com/compatibility-score/?dependency-name=factory_bot_rails&package-manager=bundler&previous-version=4.11.1&new-version=5.0.0

@chevinbrown
Copy link
Author

@composerinteralia any reason thoughtbot prefers NEWS file over something like CHANGELOG?

@jrgns
Copy link

jrgns commented Feb 8, 2019

Thanks for opening this issue. This was an intentional change; we changed the default value for use_parent_strategy to true in thoughtbot/factory_bot@d0208ed. It is indeed a breaking a change. I would be curious to know how many failures this caused in your test suite, and how long it took you to figure out what was going on.

This took us a good couple of hours to figure out, and failed on the linting step. I didn't immediately realise it had to do with a factory_bot upgrade (and we're not using rails), so it took me a while to find the documented issues.

@composerinteralia
Copy link
Collaborator

@pboling thank you for that information. That makes sense, since changing the default value for FactoryBot.use_parent_strategy was an intentional breaking change. (copied from thoughtbot/factory_bot#1255)

@chevinbrown I haven't thought much about it, but https://www.gnu.org/prep/standards/standards.html#NEWS-File seems to indicate that NEWS files are for user-visible changes, and change logs include all the details of every internal change. Our NEWS files do focus on user-visible changes.

@jrgns thanks for that feedback. I am thinking about maybe writing up a blog post with the details of why we changed the default for FactoryBot.use_parent_strategy, and how to update. I will be sure to post it here when it is ready.

@composerinteralia
Copy link
Collaborator

@tomhughes I really like the changes you made in openstreetmap/openstreetmap-website@f7694a9. Let me know if you run into any other problems.

@erikraudsepp
Copy link

Thanks for keeping the issue open and findable!
Using FactoryBot.use_parent_strategy = false seems to make the tests pass again.
We have about 25 tests failing, which is not too many, but some of the fixes wouldn't be very straight forward. I wish it would have been announced a bit more explicitly that the default value is to blame surrounding how :build behaves. It took some hours to get here.

@composerinteralia
Copy link
Collaborator

Thanks @erikraudsepp. If at some point you do tackle the failing tests, I would be curious which fixes were not straightforward.

I wish it would have been announced a bit more explicitly that the default value is to blame surrounding how :build behaves

I had thought https://github.com/thoughtbot/factory_bot/blob/806ec9f6fe071f3576aa28c804bacfc7eefc790e/NEWS#L3-L4 would be explicit enough. For the future, is there something else that would have helped you?

@chevinbrown
Copy link
Author

chevinbrown commented Feb 20, 2019

@composerinteralia re-reading this thread, I'd advocate for using CHANGELOG.md for these things. I feel that the community at large would benefit b/c things like dependabot parse that and that's usually my go-to location for...changes. 😄
It's also somewhat a general standard and understood by the community.
Maybe NEWS could be used to forecast issues/changes (like the factory-girl -> factory-bot change) and CHANGELOG.md could contain the actual API changes?

After re-rereading...
Is there just impedance b/t the rails gem changes and this one?

@composerinteralia
Copy link
Collaborator

composerinteralia commented Feb 20, 2019

@chevinbrown I think dependabot does recognize the NEWS file. I think your updated comment is right--people using factory_bot_rails might not have seen the changes listed in factory_bot's NEWS file.

@erikraudsepp
Copy link

@composerinteralia thank you for your response.

In the test we were using:

data_stream = build(:data_stream, data_streamable: @custom_field)

Which in the factory is defined as:

  factory :data_stream, traits: %i[ownable] do
    name { "Dæta Strëam #{Faker::ElderScrolls.creature.pluralize}" }
    before(:create) do |obj, _|
      StampPermission.run!(object: obj, person: obj.owner)
    end
  end

At first I thought that I would just need to change the callback before(:create) to after(:build). But after a few tries, I also noticed that now I need to pass in the owner.
data_stream = build(:data_stream, owner: @owner, data_streamable: @custom_field)
As the errors it gave were identical, I thought that the callback still didn't get run, although I changed it to after(:build).
I think the rest of the changes are identical to
openstreetmap/openstreetmap-website@f7694a9

Now after being more familiar with how factory_bot works, I think the changelog message is enough. Using factory_bot has been intuitive enough that I haven't had any need so far to familiarize myself with the readme and "use_parent_strategy" didn't click at all.

@tovodeverett
Copy link

It took me about 15 minutes to track down the issue in my app and append , strategy: :create to the association call in the do block for the affected factories.

amatriain added a commit to amatriain/feedbunch that referenced this issue Mar 14, 2019
In FactoryBot 5 there's been a change in how associations are built (new
behavior is to use the parent build strategy, old behavior... not sure
what is the strategy then).

This new behavior broke some tests. For now old behavior is restored.

The new behavior is very briefly explained in:

    https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#associations

The new (backwards-incompatible) behavior is also discussed in these
issues:

    thoughtbot/factory_bot_rails#314
    thoughtbot/factory_bot#1255

FactoryBot dev has mentioned maybe writing a blog post explaining the
rationale behind the change and how to adapt tests. In the future the
old behavior will likely get deprecated. Whenever I decide to use the
new behavior in FeedBunch I'll have to check if there's a post in the
FactoryBot blog about this.
@composerinteralia
Copy link
Collaborator

I haven't had time to write a blog post about this, but if anybody is curious about the motivation behind this change I tried to dump all of my thoughts into the commit message: thoughtbot/factory_bot@d0208ed

@chevinbrown
Copy link
Author

Thanks, @composerinteralia that's super helpful.

sihugh added a commit to alphagov/whitehall that referenced this issue Jul 30, 2019
The default value for `FactoryBot.use_parent_strategy` changed from `false`
to `true` at [v5.0.0](thoughtbot/factory_bot_rails#314)

This caused some validation errors in role creation in tests because the
attached role assignments weren't created correctly due to the new FactoryBot
configuration.

We could set `FactoryBot.use_parent_strategy = false`, but I think it's
better to update the factories themselves.
sihugh added a commit to alphagov/whitehall that referenced this issue Aug 8, 2019
The default value for `FactoryBot.use_parent_strategy` changed from `false`
to `true` at [v5.0.0](thoughtbot/factory_bot_rails#314)

This caused some validation errors in role creation in tests because the
attached role assignments weren't created correctly due to the new FactoryBot
configuration.

We could set `FactoryBot.use_parent_strategy = false`, but I think it's
better to update the factories themselves.
@andreierdoss
Copy link

Ruby 2.6.3
Rails 5.2.3

When upgrading to version 5, I am getting the can't modify frozen Hash error. I can identify two types of failures:
build / save scenario

describe '#publish_to_twitter' do
  context 'on answer create' do
    let(:answer) { build(:answer) }

    it "publish to twitter" do
      expect(answer).to receive(:publish_to_twitter)
      answer.save
    end
end

shoulda-matcher validate_uniqueness_of with scope
it { is_expected.to validate_uniqueness_of(:voter_id).scoped_to([:voteable_type, :voteable_id, :voter_type]) }
If I set FactoryBot.use_parent_strategy = false, the specs pass as before the upgrade.

sihugh added a commit to alphagov/whitehall that referenced this issue Aug 14, 2019
The default value for `FactoryBot.use_parent_strategy` changed from `false`
to `true` at [v5.0.0](thoughtbot/factory_bot_rails#314)

This caused some validation errors in artefact creation in tests because the
attached role assignments weren't created correctly due to the new FactoryBot
configuration.

We could set `FactoryBot.use_parent_strategy = false`, but I think it's
better to update the factories themselves.
sihugh added a commit to alphagov/whitehall that referenced this issue Aug 14, 2019
Some of these tests were failing because factorybot has changed the default
for creating associations. For the validations to work correctly, the
association has to have been created and persisted.  The default is now
to mirror the create/build option that the parent fixture has used.

thoughtbot/factory_bot_rails#314
@composerinteralia
Copy link
Collaborator

@andreierdoss are you able to provide a reproduction script in this format? That would make it easier to debug what is going on in your specific case. can't modify frozen Hash doesn't ring any bells for me.

edwardkerry added a commit to alphagov/whitehall that referenced this issue Sep 30, 2019
`FactoryBot.use_parent_stategy` now defaults to `true`, rather than false.

thoughtbot/factory_bot_rails#314
thoughtbot/factory_bot#1255

These  tests were failing as the new configuration prevented the test objects from being persisted for validation checks.
edwardkerry added a commit to alphagov/whitehall that referenced this issue Sep 30, 2019
`FactoryBot.use_parent_stategy` now defaults to `true`, rather than false.

thoughtbot/factory_bot_rails#314
thoughtbot/factory_bot#1255

These  tests were failing as the new configuration prevented the test objects from being persisted for validation checks.
edwardkerry added a commit to alphagov/whitehall that referenced this issue Sep 30, 2019
`FactoryBot.use_parent_stategy` now defaults to `true`, rather than false.

thoughtbot/factory_bot_rails#314
thoughtbot/factory_bot#1255

These  tests were failing as the new configuration prevented the test objects from being persisted for validation checks.
edwardkerry added a commit to alphagov/whitehall that referenced this issue Sep 30, 2019
`FactoryBot.use_parent_stategy` now defaults to `true`, rather than false.

thoughtbot/factory_bot_rails#314
thoughtbot/factory_bot#1255

These  tests were failing as the new configuration prevented the test objects from being persisted for validation checks.
edwardkerry added a commit to alphagov/whitehall that referenced this issue Sep 30, 2019
`FactoryBot.use_parent_stategy` now defaults to `true`, rather than false.

thoughtbot/factory_bot_rails#314
thoughtbot/factory_bot#1255

These  tests were failing as the new configuration prevented the test objects from being persisted for validation checks.
edwardkerry added a commit to alphagov/whitehall that referenced this issue Sep 30, 2019
`FactoryBot.use_parent_stategy` now defaults to `true`, rather than false.

thoughtbot/factory_bot_rails#314
thoughtbot/factory_bot#1255

These  tests were failing as the new configuration prevented the test objects from being persisted for validation checks.
@composerinteralia
Copy link
Collaborator

This change has been out for 10 months now, so I am going to go ahead and close this issue now. Thanks everyone for your help!

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

No branches or pull requests

8 participants