My mailer:
class MyMailer < ApplicationMailer
def notify_deactivation(client:)
mail to: client.account.email, subject: 'subject'
end
end
Running Rubocop:
app/mailers/my_mailer.rb:1:1: E: class definition in method body
(Using Ruby 2.0 parser; configure using TargetRubyVersion parameter, under AllCops)
class MyMailer < ApplicationMailer
^^^^^
0.36.0 (using Parser 2.3.0.1, running on ruby 2.3.0 x86_64-darwin15)
@lucascaton, just to clarify, what you have shown is the _entire_ source file, right?
Hi @alexdowad, correct - this is the entire file.
The issue is that RuboCop defaults to using 2.0 for the TargetRubyVersion configuration option, regardless of the minor version of Ruby 2.x you are using.
This results in code using features from newer 2.x minor versions (like required keyword arguments introduced in Ruby 2.1, as is the case in the original example) to be considered syntactically incorrect.
A default of 2.0 for any 2.x Ruby was an intentional decision, as is hinted here: 91c98d95d4b82f65095aaf78d4c627b1d989599f. Full discussion is can be found at: https://github.com/bbatsov/rubocop/issues/2575, and there's a good bit of justification for forcing a TargetRubyVersion to be specified in https://github.com/bbatsov/rubocop/pull/2655#issuecomment-172257368.
Until now I've been running RuboCop in Travis builds so that it passes for each minor Ruby version, and it's never been an issue until RuboCop 0.36.0. However, now I see why that approach doesn't quite make sense. This is documented in https://github.com/bbatsov/rubocop/blob/v0.36.0/README.md#setting-the-target-ruby-version, but I didn't discover that until I really went digging.
I wonder if adding:
You should set
TargetRubyVersionto the oldest Ruby version your project needs to support
...to the error message would help any? I could see this tripping up a lot more people otherwise.
Thanks @sds, that's really helpful.
I added TargetRubyVersion: 2.3 to my rubocop.yml and it worked.
BTW, a small suggestion: what about Rubocop identifying the current Ruby version and setting this automatically?
Cheers.
Contributors, to avoid continually getting support requests related to this feature, and continually answering the same questions over and over, I think we need a default which is:
Parser::Ruby23, since it accepts the widest range of syntaxParser::Ruby20Those who want stricter checking can set an explicit TargetRubyVersion. What do you think?
As strict as possible when checking whether an autocorrection is valid -- which probably means using Parser::Ruby20
Or we can have different auto-completions if necessary (based on the target version).
Or we can have different auto-completions if necessary (based on the target version).
Sure, absolutely. But I am making a different point here.
Making people choose a target Ruby version is causing a lot of noise on the bug tracker.
If we set the default target to a high version, like 2.3, there will be less noise from people who find that RC rejects their syntax, but more noise from people who find that autocorrection breaks their code (by using new syntax).
On the other hand, if we set it to a low version, as it is now, autocorrection won't break anyone's code (unless they were targeting Ruby 1.8 or 1.9), but there is too much noise from people who want to use 2.1+ syntax, and complain when RC flags it.
What I am proposing is a default which is optimized for "fewest GH issues".
Anyhow, this issue can be closed.
@alexdowad One one hand, what makes sense regarding the Ruby version is to infere it from .ruby-version or Gemfile files, as @thegranddesign properly arguments in #2956 - Check .ruby-version for TargetRubyVersion.
On the other hand, regarding @lucascaton original issue: class definition in method body does sound like a weird error message to explain that the analyzed code is using required keyword arguments (which weren't supported in the Ruby version RuboCop is targeting).
@lucascaton Wow lucas you are everywhere
Most helpful comment
Thanks @sds, that's really helpful.
I added
TargetRubyVersion: 2.3to myrubocop.ymland it worked.BTW, a small suggestion: what about Rubocop identifying the current Ruby version and setting this automatically?
Cheers.