Rubocop: Error "class definition in method body"

Created on 19 Jan 2016  路  10Comments  路  Source: rubocop-hq/rubocop

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)

Most helpful comment

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.

All 10 comments

@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 TargetRubyVersion to 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:

  • As lax as possible when inspecting code -- which means using Parser::Ruby23, since it accepts the widest range of syntax
  • As strict as possible when checking whether an autocorrection is valid -- which probably means using Parser::Ruby20

Those 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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kirrmann picture kirrmann  路  3Comments

tedPen picture tedPen  路  3Comments

NobodysNightmare picture NobodysNightmare  路  3Comments

bquorning picture bquorning  路  3Comments

deivid-rodriguez picture deivid-rodriguez  路  3Comments