Skip to content

Introduce FactoryGirl/FactoryClassName cop #839

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

Merged
merged 1 commit into from
Nov 20, 2019

Conversation

fragoulis
Copy link
Contributor

@fragoulis fragoulis commented Nov 14, 2019

The cop ensures that when creating factories and passing the class
name explicitly, we do not pass the class itself.

Although FactoryBot allows passing the class, we find that by doing so,
application models are loaded before the application itself gets loaded
(during factory definition).

This affects libraries like simplecov in that they fail to capture those files.

Example:

# bad
factory :foo, class: Foo do
end

# good
factory :foo, class: 'Foo' do
end

Checklist

  • Feature branch is up-to-date with master (if not - rebase it).
  • Squashed related commits together.
  • Added tests.
  • Added an entry to the changelog if the new code introduces user-observable changes.
  • The build (bundle exec rake) passes (be sure to run this locally, since it may produce updated documentation that you will need to commit).

If you have created a new cop:

  • Added the new cop to config/default.yml.
  • The cop documents examples of good and bad code.
  • The tests assert both that bad code is reported and that good code is not reported.

@fragoulis fragoulis force-pushed the factorybot/factory-class-name branch 7 times, most recently from b5ad34f to bbd8652 Compare November 15, 2019 13:10
@fragoulis fragoulis marked this pull request as ready for review November 15, 2019 13:45
Copy link
Member

@pirj pirj left a comment

Choose a reason for hiding this comment

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

What is the reasoning for this cop?
I could only find this:

If the constant is not available (if you are using a Rails engine that waits to load models, for example), you can also pass a symbol or string, which factory_bot will constantize later, once you start building objects

@pirj
Copy link
Member

pirj commented Nov 17, 2019

I actually see an additional benefit in this style. Since factories usually cover all models, all models will be auto-loaded when class is defined as a constant, which is an additional overhead if a test only needs a few of the models, and it's possible to lazily load them.

@fragoulis
Copy link
Contributor Author

What is the reasoning for this cop?

The reason behind this as mentioned in the description is application models are loaded before the application itself. I realise this is supported but I do not see any benefit in loading all application models that have a factory before they are actually needed.

The loading overhead argument you mentioned is part of my argument as well, not explicitly mentioned though.

Copy link
Member

@pirj pirj left a comment

Choose a reason for hiding this comment

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

Thanks a lot!

@fragoulis fragoulis requested a review from pirj November 18, 2019 13:03
Copy link
Member

@pirj pirj left a comment

Choose a reason for hiding this comment

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

Looks good. Thank you!

@fragoulis
Copy link
Contributor Author

Thanks for the comments. I believe this is ready.

Copy link
Member

@pirj pirj left a comment

Choose a reason for hiding this comment

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

Looks flawless!
Thanks for the contribution ❤️

Please squash the commits.
@Darhazer @bquorning please take a look.


context 'when passing block' do
context 'when a class' do
it 'registers an offense' do
Copy link
Member

@pirj pirj Nov 19, 2019

Choose a reason for hiding this comment

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

There's no guideline and even no common practice, but "ignores"/"flags" seems to be a little bit more widespread.
If you don't feel it fits the current spec structure that much, feel free to keep as is, it's good enough already.

Copy link
Contributor Author

@fragoulis fragoulis Nov 20, 2019

Choose a reason for hiding this comment

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

I guess you are referring to the use of the wording registers with the context above it.

Most of what I did I saw in other cops (factory bot ones). However, I can see there are 2 or 3 ways of doing things. It is normal for standards and common practices to change over time. It would be nice if the documentation was updated to reflect that, the best practices etc.

But anyway, it was a nice experience altogether. It will help me shape new cops for lots of things.

PS: I used the flags/ignores paradigm, I hope it is ok.

@fragoulis fragoulis force-pushed the factorybot/factory-class-name branch 3 times, most recently from ab5d473 to c5b6552 Compare November 20, 2019 08:49
@bquorning
Copy link
Collaborator

@Darhazer, any comments?

CHANGELOG.md Outdated
@@ -403,6 +403,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
* Add `RSpecMultipleDescribes` cop to check for multiple top level describes. ([@geniou][])
* Add `RSpecDescribedClass` to promote the use of `described_class`. ([@geniou][])
* Add `RSpecInstanceVariable` cop to check for the usage of instance variables. ([@geniou][])
* Add `FactoryBot/FactoryClassName` cop. ([@jfragoulis][])
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah, just one more thing. Could you move this line up towards the top of the file, as the last bullet point under ## Master (Unreleased) please.

Copy link
Collaborator

Choose a reason for hiding this comment

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

…you‘ll need to rebase on latest master too, to avoid merge conflict.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wow, what an oversight! :) :) Done and thanks!

The cop ensures that when creating factories, we do not allow
passing the class itself. Instead we require users to pass the
class name.

Although `FactoryBot` allows passing the class, we find that by doing so,
application models are loaded during application initialization and
many files are required without them having to.

This affects the startup time as well as libraries like simplecov
that fail to capture those files.

Example:

bad
```
factory :foo, class: Foo do
end
```

good
```
factory :foo, class: 'Foo' do
end
```
@fragoulis fragoulis force-pushed the factorybot/factory-class-name branch from c5b6552 to da35c8d Compare November 20, 2019 11:09
@bquorning bquorning merged commit 2be183b into rubocop:master Nov 20, 2019
@pirj
Copy link
Member

pirj commented Nov 20, 2019

Thanks and looking forward to your future contributions! 👍

@fragoulis fragoulis deleted the factorybot/factory-class-name branch November 20, 2019 12:09
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.

4 participants