Rubocop, how to Disable/Enable cops on blocks of code - ruby

I will like to disable a cop for a specific block or method.
I know it is possible to disable a cop for the whole project using .rubocop.yml but I just want to deactivate the cop temporarily for a specific portion of the code

I answer my question because it is always very difficult for me to find the reference to this solution:
# rubocop:disable Metrics/MethodLength
def my_code
..
end
# rubocop:enable Metrics/MethodLength
Same for multiple cops:
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
def my_code
..
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
Documentation: https://docs.rubocop.org/rubocop/configuration.html#disabling-cops-within-source-code

If you want to disable the cop for a particular line, you can just use something like this
before_action :authenticate_user!, except: [:index, :show] # rubocop:disable Style/SymbolArray
No need to enable it again. If there is a block of code and you want to enable or disable the cop, then as suggested above, you can follow that approach.

Related

RuboCop complains when using 'Hash.new'

RuboCop complains when I use Hash.new, and suggests that I instead use a hash literal. Is there a way to make RuboCop ignore uses of Hash.new? More specifically, can I edit my .rubocop.yml configuration to allow the use of Hash.new without raising any complaints?
You can disable the Rubocop::Cop::Style::EmptyLiteral cop within the rubocop.yml file:
# .rubocop.yml
Style:
EmptyLiteral: false
Or if you want just to ignore a certain line:
hsh = Hash.new # rubocop:disable Style/EmptyLiteral
According to Ruby Style Guide literal array and hash creation notation are preferred unless you need to pass parameters to their constructors. So, to follow the guide you should use hash = {} instead hash = Hash.new.
I would follow the conventions in the guide, but in case that you do not want, you can disable the Style/EmptyLiteral cop, as for any other cop, either locally or globally.
Globally
Add to you rubocop.yml file:
Style:
EmptyLiteral: false
Locally
# rubocop:disable Style/EmptyLiteral
hash = Hash.new
# rubocop:enable Style/EmptyLiteral
or the short version for a single line:
hash = Hash.new # rubocop:disable Style/EmptyLiteral
For more information about how to configure Rubocop check its documentation.

# rubocop:disable Metrics/AbcSize

I am really stuck in this part:
If i disable # rubocop:disable Metrics/AbcSize, then I am getting this error:
ruby -v : ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-darwin14]
rubocop -V
0.52.1 (using Parser 2.4.0.2, running on ruby 2.4.2 x86_64-darwin14)
$ rubocop .
Inspecting 7 files
.....W.
Offenses:
recipes/default.rb:13:1: W: Lint/MissingCopEnableDirective: Re-enable Metrics/AbcSize cop with # rubocop:enable after disabling it.
# rubocop:disable Metrics/AbcSize
^
7 files inspected, 1 offense detected
If I enable rubocop in the script then getting this:
rubocop .
Inspecting 7 files
.....C.
Offenses:
recipes/default.rb:31:1: C: Metrics/AbcSize: Assignment Branch Condition size for check_tropo_versions is too high. [33.02/20]
def check_tropo_versions ...
^^^^^^^^^^^^^^^^^^^^^^^^
7 files inspected, 1 offense detected
A few lines of my script:
# rubocop:enable Metrics/AbcSize
require 'nokogiri'
Chef.event_handler do
on :resource_updated do |resource, _action|
if resource.declared_type.to_s == 'remote_file' && resource.cookbook_name == 'tropo-patch' && resource.recipe_name == 'default'
puts "#{Time.now.strftime('%Y%m%d%H%M%S')},#{resource.path},#{resource.source[0]}"
File.open('/var/log/tropo-patch.log', 'a') { |f| f.write("#{Time.now.strftime('%Y%m%d%H%M%S')},#{resource.path},#{resource.source[0]}\n") }
end
end
end
I cannot disable rubocop from global config file, but if it can resolve I will try this as well:
Metrics/AbcSize:
Description: >-
A calculated magnitude based on number of assignments,
branches, and conditions.
Reference: 'http://c2.com/cgi/wiki?AbcMetric'
Enabled: true
What Rubocop is basically complaining about is that it asks you to enable the cop after the method is closed, so the cop can be in effect for other methods of the file. If you disable it on the first line of the file, it will be disable for all methods in that file. Disabling cops for whole files is not a good idea, since you should be explicit and conscious when disabling the cops.
The fix in your case is just simply disabling the cop before your method, and then enable it after.
For example:
# rubocop:disable Metrics/AbcSize
require 'nokogiri'
Chef.event_handler do
on :resource_updated do |resource, _action|
if resource.declared_type.to_s == 'remote_file' && resource.cookbook_name == 'tropo-patch' && resource.recipe_name == 'default'
puts "#{Time.now.strftime('%Y%m%d%H%M%S')},#{resource.path},#{resource.source[0]}"
File.open('/var/log/tropo-patch.log', 'a') { |f| f.write("#{Time.now.strftime('%Y%m%d%H%M%S')},#{resource.path},#{resource.source[0]}\n") }
end
end
end
# rubocop:enable Metrics/AbcSize
Also, if you need to disable multiple cops, you can enable all of them by using:
# rubocop:enable all
Hope that helps!
Edit: After looking at Tom Lord's comment on your question, I noticed that you haven't posted the actual method that is breaking the rule of the cop. Still, the solution I provided should work if your put the disable and enable statements at the correct places. In addition, I second what Tom stated, that if you show us the code we might improve the method and you will not need to disable the cop for the method.
You can disable a cop for this method only, instead of adding # rubocop:disable at the top of the file, just mark your offender like this
def check_tropo_versions # rubocop:disable Metrics/AbcSize
# ...
Use cookstyle in place of rubocop there. It’s got better defaults for linting cookbook code.

How can I validate a date string without rescuing the exception to keep the Rubocop HandleExceptions linter happy?

I have a string which might or might not be a valid date.
I want a clean and simple way to validate whilst keeping Rubocop happy.
# TODO: Welcome suggestions for a better way to deal with this...
# rubocop:disable HandleExceptions
def self.valid_date?(date)
Date.parse(date)
rescue ArgumentError
end
# rubocop:enable HandleExceptions
I actually feel like this is a clean way to achieve what I need, but is there a way to resolve whilst still keeping rubocop happy?
Add a explicit nil:
# TODO: Welcome suggestions for a better way to deal with this...
# rubocop:disable HandleExceptions
def self.valid_date?(date)
Date.parse(date)
rescue ArgumentError
nil
end
Otherwise, enable inline rescue in .rubocop.yml for a shorter method:
Style/RescueModifier:
Enabled: false
Then:
# TODO: Welcome suggestions for a better way to deal with this...
# rubocop:disable HandleExceptions
def self.valid_date?(date)
Date.parse(date) rescue nil
end
Remember, how readable is your code does not deppend on what a machine says, but what other people (i.e. a community) feel about it. Rubocop is just a tool for a quick way to review code without reading line by line manually.
# rubocop:disable Style/RescueModifier
def self.valid_date?(date)
Date.parse(date) rescue nil
end
# rubocop:enable Style/RescueModifier

How can I skip some setup for specific Rspec tags?

Rspec makes it easy to configure setup based on the presence of test tags. For example, if some tests need a parallel universe to be created (assuming you have code to do that):
# some_spec.rb
describe "in a parallel universe", alter_spacetime: true do
# whatever
end
# spec_helper.rb
RSpec.configure do |config|
config.before(:each, :alter_spacetime) do |example|
# fancy magic here
end
end
But I want to do the opposite: "before each test, unless you see this tag, do the following..."
How can I skip a setup step in spec_helper based on the presence of a tag on some tests?
At first, you would expect something like
RSpec.configure do |config|
config.before(:each, alter_spacetime: false) do |example|
# fancy magic here
end
end
to work that way, but it doesn't.
But you have access to example, which is an Example instance and has the #metadata method, which returns Metadata object. You can check the value of the flag with that, and a flag on the specific example will override one on the containing describe block.
config.before(:each) do |example|
# Note that we're not using a block param to get `example`
unless example.metadata[:alter_spacetime] == false
# fancy magic here
end
end

How do you disable awesome_print once enabled in IRB or rails console?

I have awesome_print configured to be my default formatter in IRB (using AwesomePrint.irb! in my .irbrc) and while this is normally awesome, I want to turn it off sometimes. Anybody know how to from a running IRB/Rails console?
You can paste this in to you terminal to reset it back to what it was originally if you like:
IRB::Irb.class_eval do
def output_value # :nodoc:
printf #context.return_format, #context.inspect_last_value
end
end
or you can go whole hog and monkey patch AwesomePrint:
module AwesomePrint
def self.un_irb!
IRB::Irb.class_eval do
def output_value # :nodoc:
printf #context.return_format, #context.inspect_last_value
end
end
end
end
Then just call it whenever you want: AwesomePrint.un_irb!

Resources