Add RSpec/FactoryBot/AssociationStyle cop#1414
Add RSpec/FactoryBot/AssociationStyle cop#1414r7kamura wants to merge 1 commit intorubocop:masterfrom
RSpec/FactoryBot/AssociationStyle cop#1414Conversation
|
It seems that over time, all the three progressed. I was still believing that the implicit way didn't allow specifying Personally, I strongly prefer the inline definition, for three reasons:
The downside is that it's the most verbose out of the three in most of the cases.
Is there anything else that I'm missing? |
pirj
left a comment
There was a problem hiding this comment.
Looks good as is. Up to you if you tend to keep it like that, and leave improvements for follow-up PRs/tickets.
The only thing left to do is to run it against real-world-rspec and see which style is most frequently used in the wild to minimize the impact and follow what people really use. I can run this for you if you like.
| author do | ||
| association :user | ||
| end |
There was a problem hiding this comment.
Could be written as implicit author factory: :user, so I'd count this as an offence.
It's the inline style that we don't detect, but not really "inline" 😄
|
The The for e.g.: FactoryBot.define do
factory :like, class: Carto::Like do
end
end factory 'valid site' do
# after(:build) { |valid_site| valid_site.stubs(:valid?).returns(true) }
end |
|
Implicit: Explicit: Going with the implicit as the default enforced style seems reasonable 👍 |
82ba67f to
3bd988f
Compare
As noted in the documentation, attributes defined by inline-style always appears with # implicit
FactoryBot.define do
factory :article do
user
end
end
FactoryBot.attributes_for(:article) #=> {}# explicit
FactoryBot.define do
factory :article do
association :user
end
end
FactoryBot.attributes_for(:article) #=> {}# inline
FactoryBot.define do
factory :article do
user { association :user }
end
end
FactoryBot.attributes_for(:article) #=> {:user => nil}
For that reason, it would be difficult to safely say that this is an offense 🤔 My personal preference is to use inline-style only when I need it and not otherwise. If I always use inline-style, it makes difficult to infer from the code whether I am doing so because inline-style is necessary in the case or not. If there seems to be a certain number of people who want to use the inline-style all the time, it might be nice to have a style in this cop that always prefers the inline-style. The downside is that it is quite difficult to autocorrect from inline-style to the other styles for the reasons mentioned above. |
pirj
left a comment
There was a problem hiding this comment.
A couple of cosmetic suggestions
2d2594a to
417a51d
Compare
|
|
I can also think of |
It seems that the implicit style does not allow such trait usage, so I need to fix # frozen_string_literal: true
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'factory_bot'
end
FactoryBot.define do
factory :article do
trait :active do
active { true }
end
end
factory :comment do
article :active
end
endInstead, it can be written by using # frozen_string_literal: true
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'activerecord', '~> 7.0.0'
gem 'factory_bot'
gem 'sqlite3'
end
require 'active_record'
require 'logger'
require 'minitest/autorun'
ActiveRecord::Base.establish_connection(
adapter: 'sqlite3',
database: ':memory:'
)
ActiveRecord::Schema.define do
create_table :articles, force: true do |t|
t.boolean :active, default: false
end
create_table :comments, force: true do |t|
t.references :article
end
end
class Article < ActiveRecord::Base
end
class Comment < ActiveRecord::Base
belongs_to :article
end
FactoryBot.define do
factory :article do
trait :active do
active { true }
end
end
factory :comment do
article factory: [:article, :active]
end
end
class FactoryTest < Minitest::Test
def test_association
assert ::FactoryBot.create(:comment).article.active
end
end |
|
I might be talking nonsense, but as an alternative to article factory: [:article, :active]would it be possible to write it as article traits: [:active]Which one would you prefer? |
|
I feel you. I actually tried that example before posting the previous comment too, but I couldn't use Perhaps only I created the following Pull Request on thoughtbot/factory_bot: |
85aa570 to
a5ca5b4
Compare
| NonImplicitAssociationMethodNames: | ||
| - association | ||
| - skip_create | ||
| - traits_for_enum |
There was a problem hiding this comment.
Does this have to be user configurable?
There was a problem hiding this comment.
Certainly there is no need to make these default values removable. The main reason why I have this config value is for Global sequences.
Factory.define do
sequence(:email) { |n| "person#{n}@example.com" }
factory :user do
email
end
end9a6b052 to
889ee79
Compare
2c8aaed to
fa28f48
Compare
fa28f48 to
957caf9
Compare
| # # good (defined in NonImplicitAssociationMethodNames) | ||
| # skip_create |
There was a problem hiding this comment.
What do you think of using something that looks like an global sequence attribute call here, e.g. email?
| # # good (defined in NonImplicitAssociationMethodNames) | |
| # skip_create | |
| # # good (defined in NonImplicitAssociationMethodNames) | |
There was a problem hiding this comment.
Looks good 👍
Besides, now that skip_create is set by constant instead of config, it is strange that this value is used as an example here.
74abfcc to
7666577
Compare
7666577 to
007543f
Compare
|
@r7kamura Would you re-target this to |
|
Recreated on rubocop-factory_bot repo: |

In FactoryBot, there are 2 ways to define associations.
These styles are documented at the following section:
(Stricyly speaking, there is also inline style, but it behaves differently from the above 2 styles.)
It would be nice to have a cop for consistent use of only one of the styles. This Pull Request has been created for this purpose.
Before submitting the PR make sure the following are checked:
master(if not - rebase it).CHANGELOG.mdif the new code introduces user-observable changes.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:
config/default.yml.Enabled: pendinginconfig/default.yml.Enabled: truein.rubocop.yml.VersionAddedindefault/config.ymlto the next minor version.If you have modified an existing cop's configuration options:
VersionChangedinconfig/default.ymlto the next major version.