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

FactoryBot/ConsistentParenthesesStyle in disagree with Style/HashSyntax when enforcing omit_parentheses in before blocks #135

Open
hfvmarques opened this issue Oct 28, 2024 · 7 comments · May be fixed by #136

Comments

@hfvmarques
Copy link

It's been a while that sometimes I'm getting this. I always have a "workaround" but it's not pretty, but I think that this could be addressed properly.

When you have a before block, and inside there is more than a factory, and within that creates/builds there are hashes with the same name in key/value, there is a crossroad (I don't know if that's a good word). I'll explain:

before do
  create :entity, :with_this_trait, :with_that_trait, user: user
  create :other_entity, :with_this_trait, :with_that_trait, user: user
end

The code above raises the flag of Style/HashSyntax, so we have to do this:

before do
  create :entity, :with_this_trait, :with_that_trait, user:
  create :other_entity, :with_this_trait, :with_that_trait, user: 
end

But the code above does not run because of Ruby sintax error, so we have to do this:

before do
  create(:entity, :with_this_trait, :with_that_trait, user:)
  create(:other_entity, :with_this_trait, :with_that_trait, user:)
end

But if you have the omit_parenthesis EnforcedStyle, it raises the flag of FactoryBot/ConsistentParenthesesStyle.

So, there you have it. Sometime when there are other attributes to use, I put the last one that does not have the same name in key/value such as this:

before do
  create :entity, :with_this_trait, :with_that_trait, user:, other_attribute: variable
  create :other_entity, :with_this_trait, :with_that_trait, user:, other_attribute: other_variable
end

Or even get some more lines in it like this:

before do
  create(
    :entity, :with_this_trait, :with_that_trait, user:
  )
  create(
    :other_entity, :with_this_trait, :with_that_trait, user:
  )
end

But that's very ugly.

So, do you guys think this is a ruby problem, a rubocop problem or a rubocop-factory_bot problem?

@pirj
Copy link
Member

pirj commented Oct 28, 2024

Do I read it correctly that Style/HashSyntax‘s autocorrection is causing syntax errors? Can you open an issue with them?

I’m not too familiar with the syntax, it looks like it expects the value for the keyword argument on the next line?

I am not convinced that this “shorthand” syntax is for the good, as it makes it less obvious that many keyword arguments are fine, when they usually are a sign of a design that can be improved.

To me, I’d say that it’s Style/HashSyntax‘s problem with autocorrecting, and that it shouldn’t even bother RSpec DSL, and would recommend disabling it in spec/.rubocop.yml

@thejonroberts
Copy link

Another reason I suggested this rule is disabled by default in #132 - these are just method calls, let rubocops for general method calls handle them. create/build/build_stubbed do not need their own special rules for most projects.

And I understand it is a bit controversial, but I love the shorthand syntax, @pirj - but yes, it will not work with a newline after the colon, must be within parens or curly brackets.

@pirj
Copy link
Member

pirj commented Nov 19, 2024

Good point. It’s not for me to judge the Ruby syntax.

Do you think it will do the job if both cops are smart enough not to remove parentheses when the shorthand hash syntax is used?
Or is there anything else?
Should they still raise an offence, or should this case be treated as “ok’ish”?

@thejonroberts
Copy link

Just my two cents... Ideally, this cop would allow parentheses when there the shorthand syntax is used (AND that is allowed by Style/HashSyntax EnforcedShorthandSyntax option). Otherwise, this should probably be considered an unsafe auto-correct since it could cause syntax errors if parens removed when the shorthand syntax is used.

@pirj
Copy link
Member

pirj commented Nov 20, 2024

Exactly my thinking, @thejonroberts 👍

I believe, both this cop and that other one from rubocop will need a check for shorthand syntax.

Do you want to send a PR?

@thejonroberts
Copy link

I will take a crack at it! But anyone else interested, go for it - This would be my first time in this or any rubocop/linting/AST project's codebase. It will also be in my spare time. So I have no idea how long it will take.

@thejonroberts
Copy link

thejonroberts commented Nov 20, 2024

Investigation note: it seems that the hash syntax / hash pinning consideration was taken care of in #86 , but :omit_hash_value? does not work when a trait is used.

That is, create(:user, :trait, name:) gives an (unintended?) offense,
whereas create(:user, name:) is ignored

thejonroberts added a commit to thejonroberts/rubocop-factory_bot that referenced this issue Nov 21, 2024
When ConsistentParenthesesStyle is :omit_parentheses, we ignore factory
calls that have an omitted hash value (ruby 3.1 shorthand syntax).
Parentheses are required if the arguments end with the key of the
omitted value. (e.g. `create(:user, name:)`)
However, if a trait was used, (e.g. `create(:user, :trait, name:)`)
omit_hash_value? matcher did not match it, and thus would remove the
parentheses, potentially causing a syntax error.

This change adds a wildcard to the omit_hash_value matcher to allow
any number of symbols at the start of the factory call
(before the hash values).

see rubocop#135
thejonroberts added a commit to thejonroberts/rubocop-factory_bot that referenced this issue Nov 21, 2024
When ConsistentParenthesesStyle is :omit_parentheses, we ignore factory
calls that have an omitted hash value (ruby 3.1 shorthand syntax).
Parentheses are required if the arguments end with the key of the
omitted value. (e.g. `create(:user, name:)`)
However, if a trait was used, (e.g. `create(:user, :trait, name:)`)
omit_hash_value? matcher did not match it, and thus would remove the
parentheses, potentially causing a syntax error.

This change adds a wildcard to the omit_hash_value? matcher to allow
any number of symbols/traits at the start of the pattern
(before the hash values).

see rubocop#135
pirj pushed a commit to thejonroberts/rubocop-factory_bot that referenced this issue Nov 21, 2024
When ConsistentParenthesesStyle is :omit_parentheses, we ignore factory
calls that have an omitted hash value (ruby 3.1 shorthand syntax).
Parentheses are required if the arguments end with the key of the
omitted value. (e.g. `create(:user, name:)`)
However, if a trait was used, (e.g. `create(:user, :trait, name:)`)
omit_hash_value? matcher did not match it, and thus would remove the
parentheses, potentially causing a syntax error.

This change adds a wildcard to the omit_hash_value? matcher to allow
any number of symbols/traits at the start of the pattern
(before the hash values).

see rubocop#135
pirj pushed a commit to thejonroberts/rubocop-factory_bot that referenced this issue Nov 21, 2024
When ConsistentParenthesesStyle is :omit_parentheses, we ignore factory
calls that have an omitted hash value (ruby 3.1 shorthand syntax).
Parentheses are required if the arguments end with the key of the
omitted value. (e.g. `create(:user, name:)`)
However, if a trait was used, (e.g. `create(:user, :trait, name:)`)
omit_hash_value? matcher did not match it, and thus would remove the
parentheses, potentially causing a syntax error.

This change adds a wildcard to the omit_hash_value? matcher to allow
any number of symbols/traits at the start of the pattern
(before the hash values).

see rubocop#135
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants