Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Beginner's Guide to RuboCop in Rails
Truemark Technology profile imagePrabin Poudel
Prabin Poudel forTruemark Technology

Posted on • Edited on • Originally published atprabinpoudel.com.np

     

Beginner's Guide to RuboCop in Rails

RuboCop is a static code analyzer which analyzes the code based on the best practices followed by the Ruby developers around the world and defined on the communityRuby style guide.

Apart from analyzing the code, it also provides us the feature of automatically formatting the code and fix warnings inside our code.

If you are coming from Javascript background, you may have heard about ESLint.

RuboCop is ESLint for Ruby

Apart from Ruby, RuboCop also provides gems for implementing rules on various extensions like Rails, Minitest, RSpec, etc.

Why RuboCop?

It begs the question and curiosity among us, so why do we actually need RuboCop? What's the use of having RuboCop in our projects.

Here are some reasons on why we would want to use RuboCop in our projects:

  1. Clean code

    We all want to write clean code that adheres to best practices followed by developers around the world. Best practices comes from experience, it may take some years to know about the language and know the anti-patterns and good patterns to follow if we only rely on ourselves.

    With RuboCop, we have the advantage of not having the experience because best practices have been bundled as rules and shipped to us inside the "rubocop" gem. RuboCop throws warnings whenever we violate rules configured for best practices and after fixing these issues, our code is most of the time clean and easy to understand.

  2. Eases the code review process

    The main purpose of code review is to fix logics in the code, or fix security vulnerabilities or discuss the path we took to develop the feature.

    But hey, imagine a situation where we push a code with a typo and reviewer spots that, then comments on it for fixing because obviously no one wants to ship the code with typo to production!

    What's wrong with that? It takes significant time to review the code, and with typo or discussion about best practices in merge requests, we as a developer are wasting a lot of time which could have easily be solved with the help of RuboCop by configuring rules.

    RuboCop makes sure that code with issues never makes it to the merge/pull requests.

  3. Best practice is no one size fits all

    Normally best practices means what we like or dislike about the code or pattern we follow when we write the code and it differs for each one of us. If we focus our energy in discussing these practices in the code for every feature, when will we ship features?

    With RuboCop, we can discuss with the team on what best practices should the team follow and disable or enable rules based on the conclusion, hence making everyone happy (well, you can never make everyone happy!).

Setup RuboCop in Rails

In this article, we will be installing main 'rubocop' gem for implementing rules in Ruby code along with the extension 'rubocop-rails' for Rails specific code.

Add Gems to Gemfile

Add the following to Gemfile inside the group:development, :test

group:development,:testdo# enforce rails best practice with rubocopgem'rubocop','~> 1.18.0',require:falsegem'rubocop-performance','~> 1.11.0',require:falsegem'rubocop-rails','~> 2.11.0',require:falseend
Enter fullscreen modeExit fullscreen mode

NOTE: Update gem versions based on what is latest at the time you are installing these gems in our project

We have added the following gems to our Gemfile:

  • rubocop: For Ruby code
  • rubocop-performance: For code performance related rules
  • rubocop-rails: For Rails specific rules

Install Gems in the Project

  1. Install rubocop globally

    gem install rubocop

    This will help us in running commands provided by 'rubocop' gem like auto formatting, running rubocop in the project, etc.

  2. Install new gems withbundle install

Add Configuration Files

To control (enable/disable) rules, we need to create configuration files for each extension. If there is no file then RuboCop will enable default extensions. I like to have configuration files because it provides flexibility to team.

Let's create configuration files for RuboCop and it's extensions:

  $ cd /path/to/our/project  $ touch .rubocop.yml  $ touch .rubocop-performance.yml  $ touch .rubocop-rails.yml
Enter fullscreen modeExit fullscreen mode

Add Rules to Configuration files

I also have a blog written specifically for configuration files of RuboCop, you can find it atRuboCop Configuration Files for Rails if you want more options.

Let's update configuration files and add rules for Ruby and installed extensions.

Ruby

# .rubocop.yml# The behavior of RuboCop can be controlled via the .rubocop.yml# configuration file. It makes it possible to enable/disable# certain cops (checks) and to alter their behavior if they accept# any parameters. The file can be placed either in your home# directory or in some project directory.## RuboCop will start looking for the configuration file in the directory# where the inspected file is and continue its way up to the root directory.#inherit_from:-'.rubocop-performance.yml'-'.rubocop-rails.yml'require:-rubocop-performance-rubocop-railsAllCops:TargetRubyVersion:2.7TargetRailsVersion:6.0Exclude:-'**/db/migrate/*'-'db/schema.rb'-'**/Gemfile.lock'-'**/Rakefile'-'**/rails'-'**/vendor/**/*'-'**/spec_helper.rb'-'node_modules/**/*'-'bin/*'################################################################################# RuboCop ######################################################################################## You can find all configuration options for rubocop here: https://docs.rubocop.org/rubocop/cops_bundler.html################################################################################## Gemspec ######################################################################################Gemspec/DateAssignment:# (new in 1.10)Enabled:true################################################################################### Layout ######################################################################################Layout/ClassStructure:ExpectedOrder:-module_inclusion-constants-association-public_attribute_macros-public_delegate-macros-initializer-public_class_methods-public_methods-protected_attribute_macros-protected_methods-private_attribute_macros-private_delegate-private_methodsLayout/EmptyLineAfterMultilineCondition:Enabled:trueLayout/EmptyLinesAroundAttributeAccessor:Enabled:trueLayout/FirstArrayElementIndentation:EnforcedStyle:consistentLayout/FirstArrayElementLineBreak:Enabled:trueLayout/FirstHashElementIndentation:EnforcedStyle:consistentLayout/FirstHashElementLineBreak:Enabled:trueLayout/LineEndStringConcatenationIndentation:# (new in 1.18)Enabled:trueLayout/LineLength:Max:150Exclude:-'**/spec/**/*'Layout/MultilineArrayBraceLayout:EnforcedStyle:new_lineLayout/MultilineOperationIndentation:EnforcedStyle:indentedLayout/MultilineHashBraceLayout:EnforcedStyle:new_lineLayout/MultilineHashKeyLineBreaks:Enabled:trueLayout/MultilineMethodCallBraceLayout:EnforcedStyle:new_lineLayout/MultilineMethodDefinitionBraceLayout:EnforcedStyle:new_lineLayout/SpaceAroundMethodCallOperator:Enabled:trueLayout/SpaceBeforeBrackets:# (new in 1.7)Enabled:trueLayout/SpaceInLambdaLiteral:EnforcedStyle:require_space################################################################################### Lint ########################################################################################Lint/AmbiguousAssignment:# (new in 1.7)Enabled:trueLint/AmbiguousBlockAssociation:Exclude:-'**/spec/**/*'Lint/AssignmentInCondition:AllowSafeAssignment:falseLint/BinaryOperatorWithIdenticalOperands:Enabled:trueLint/DeprecatedConstants:# (new in 1.8)Enabled:trueLint/DeprecatedOpenSSLConstant:Enabled:trueLint/DuplicateBranch:# (new in 1.3)Enabled:trueLint/DuplicateElsifCondition:Enabled:trueLint/DuplicateRegexpCharacterClassElement:# (new in 1.1)Enabled:trueLint/DuplicateRequire:Enabled:trueLint/DuplicateRescueException:Enabled:trueLint/EmptyBlock:# (new in 1.1)Enabled:trueLint/EmptyClass:# (new in 1.3)Enabled:trueLint/EmptyConditionalBody:Enabled:trueLint/EmptyFile:Enabled:trueLint/EmptyInPattern:# (new in 1.16)Enabled:trueLint/FloatComparison:Enabled:trueLint/LambdaWithoutLiteralBlock:# (new in 1.8)Enabled:trueLint/MissingSuper:Enabled:trueLint/MixedRegexpCaptureTypes:Enabled:trueLint/NoReturnInBeginEndBlocks:# (new in 1.2)Enabled:trueLint/NumberConversion:Enabled:trueLint/NumberedParameterAssignment:# (new in 1.9)Enabled:trueLint/OrAssignmentToConstant:# (new in 1.9)Enabled:trueLint/RaiseException:Enabled:trueLint/RedundantDirGlobSort:# (new in 1.8)Enabled:trueLint/SelfAssignment:Enabled:trueLint/SymbolConversion:# (new in 1.9)Enabled:trueLint/ToEnumArguments:# (new in 1.1)Enabled:trueLint/TrailingCommaInAttributeDeclaration:Enabled:trueLint/TripleQuotes:# (new in 1.9)Enabled:trueLint/UnexpectedBlockArity:# (new in 1.5)Enabled:trueLint/UnmodifiedReduceAccumulator:# (new in 1.1)Enabled:trueLint/UnusedBlockArgument:IgnoreEmptyBlocks:falseLint/UnusedMethodArgument:IgnoreEmptyMethods:falseLint/UselessMethodDefinition:Enabled:true################################################################################### Metric ######################################################################################Metrics/AbcSize:Max:45Metrics/BlockLength:CountComments:falseMax:50Exclude:-'**/spec/**/*'-'**/*.rake'-'**/factories/**/*'-'**/config/routes.rb'Metrics/ClassLength:CountAsOne:['array','hash']Max:150Metrics/CyclomaticComplexity:Max:10Metrics/MethodLength:CountAsOne:['array','hash']Max:30Metrics/ModuleLength:CountAsOne:['array','hash']Max:250Exclude:-'**/spec/**/*'Metrics/PerceivedComplexity:Max:10################################################################################### Naming ######################################################################################Naming/InclusiveLanguage:# (new in 1.18)Enabled:true################################################################################### Style #######################################################################################Style/AccessorGrouping:Enabled:trueStyle/ArgumentsForwarding:# (new in 1.1)Enabled:trueStyle/ArrayCoercion:Enabled:trueStyle/AutoResourceCleanup:Enabled:trueStyle/BisectedAttrAccessor:Enabled:trueStyle/CaseLikeIf:Enabled:trueStyle/ClassAndModuleChildren:Enabled:falseStyle/CollectionCompact:# (new in 1.2)Enabled:trueStyle/CollectionMethods:Enabled:trueStyle/CombinableLoops:Enabled:trueStyle/CommandLiteral:EnforcedStyle:percent_xStyle/ConstantVisibility:Enabled:trueStyle/Documentation:Enabled:falseStyle/DocumentDynamicEvalDefinition:# (new in 1.1)Enabled:trueStyle/EndlessMethod:# (new in 1.8)Enabled:trueStyle/ExplicitBlockArgument:Enabled:trueStyle/GlobalStdStream:Enabled:trueStyle/HashConversion:# (new in 1.10)Enabled:trueStyle/HashEachMethods:Enabled:trueStyle/HashExcept:# (new in 1.7)Enabled:trueStyle/HashLikeCase:Enabled:trueStyle/HashTransformKeys:Enabled:trueStyle/HashTransformValues:Enabled:trueStyle/IfWithBooleanLiteralBranches:# (new in 1.9)Enabled:trueStyle/ImplicitRuntimeError:Enabled:trueStyle/InlineComment:Enabled:trueStyle/InPatternThen:# (new in 1.16)Enabled:trueStyle/IpAddresses:Enabled:trueStyle/KeywordParametersOrder:Enabled:trueStyle/MethodCallWithArgsParentheses:Enabled:trueStyle/MissingElse:Enabled:trueStyle/MultilineInPatternThen:# (new in 1.16)Enabled:trueStyle/MultilineMethodSignature:Enabled:trueStyle/NegatedIfElseCondition:# (new in 1.2)Enabled:trueStyle/NilLambda:# (new in 1.3)Enabled:trueStyle/OptionalBooleanParameter:Enabled:trueStyle/QuotedSymbols:# (new in 1.16)Enabled:trueStyle/RedundantArgument:# (new in 1.4)Enabled:trueStyle/RedundantAssignment:Enabled:trueStyle/RedundantBegin:Enabled:trueStyle/RedundantFetchBlock:Enabled:trueStyle/RedundantFileExtensionInRequire:Enabled:trueStyle/RedundantSelfAssignment:Enabled:trueStyle/SingleArgumentDig:Enabled:trueStyle/StringChars:# (new in 1.12)Enabled:trueStyle/StringConcatenation:Enabled:trueStyle/SwapValues:# (new in 1.1)Enabled:true
Enter fullscreen modeExit fullscreen mode

Rails

# .rubocop-rails.yml############################################################################### RuboCop Rails #################################################################################### You can find all configuration options for rubocop-rails here: https://docs.rubocop.org/rubocop-rails/cops_rails.htmlRails/ActiveRecordCallbacksOrder:Enabled:trueRails/AddColumnIndex:# (new in 2.11)Enabled:trueRails/AfterCommitOverride:Enabled:trueRails/AttributeDefaultBlockValue:# (new in 2.9)Enabled:trueRails/DefaultScope:Enabled:trueRails/EagerEvaluationLogMessage:# (new in 2.11)Enabled:trueRails/ExpandedDateRange:# (new in 2.11)Enabled:trueRails/FindById:Enabled:trueRails/I18nLocaleAssignment:# (new in 2.11)Enabled:trueRails/Inquiry:Enabled:trueRails/MailerName:Enabled:trueRails/MatchRoute:Enabled:trueRails/NegateInclude:Enabled:trueRails/OrderById:Enabled:trueRails/Pluck:Enabled:trueRails/PluckId:Enabled:trueRails/PluckInWhere:Enabled:trueRails/RenderInline:Enabled:trueRails/RenderPlainText:Enabled:trueRails/SaveBang:Enabled:trueAllowImplicitReturn:falseRails/ShortI18n:Enabled:trueRails/SquishedSQLHeredocs:# (new in 2.8)Enabled:trueRails/TimeZoneAssignment:# (new in 2.10)Enabled:trueRails/UnusedIgnoredColumns:# (new in 2.11)Enabled:trueRails/WhereEquals:# (new in 2.9)Enabled:trueRails/WhereExists:Enabled:trueRails/WhereNot:Enabled:true
Enter fullscreen modeExit fullscreen mode

Performance

.rubocop-performance.yml############################################################################### RuboCop Performance ############################################################################## You can find all configuration options for rubocop-performance here: https://docs.rubocop.org/rubocop-performance/Performance/AncestorsInclude:# (new in 1.7)Enabled:truePerformance/BigDecimalWithNumericArgument:# (new in 1.7)Enabled:truePerformance/BlockGivenWithExplicitBlock:# (new in 1.9)Enabled:truePerformance/CollectionLiteralInLoop:# (new in 1.8)Enabled:truePerformance/ConstantRegexp:# (new in 1.9)Enabled:truePerformance/MapCompact:# (new in 1.11)Enabled:truePerformance/MethodObjectAsBlock:# (new in 1.9)Enabled:truePerformance/RedundantEqualityComparisonBlock:# (new in 1.10)Enabled:truePerformance/RedundantSortBlock:# (new in 1.7)Enabled:truePerformance/RedundantSplitRegexpArgument:# (new in 1.10)Enabled:truePerformance/RedundantStringChars:# (new in 1.7)Enabled:truePerformance/ReverseFirst:# (new in 1.7)Enabled:truePerformance/SortReverse:# (new in 1.7)Enabled:truePerformance/Squeeze:# (new in 1.7)Enabled:truePerformance/StringInclude:# (new in 1.7)Enabled:truePerformance/Sum:# (new in 1.8)Enabled:true
Enter fullscreen modeExit fullscreen mode

Run RuboCop

We have the option to run RuboCop on

  • Whole project
  • Files inside single folder
  • Only on single file

After running commands of RuboCop in the command line, we will be presented with issues found in our code inside the project, which we can then fix manually or also have option to auto correct issues in most cases.

Whole Project

  $ cd /path/to/your/project  $ rubocop
Enter fullscreen modeExit fullscreen mode

Files inside single folder

  $ rubocop app
Enter fullscreen modeExit fullscreen mode

Single file

  $ rubocop app/models/user.rb
Enter fullscreen modeExit fullscreen mode

Auto fix warnings

RubCop also provides the feature of auto correcting issues in our code.

There are a couple of things to keep in mind about auto-correct:

  • For some offenses, it is not possible to implement automatic correction.
  • Some automatic corrections that are possible have not been implemented yet.
  • Some automatic corrections might change (slightly) the semantics of the code, meaning they’d produce code that’s mostly equivalent to the original code, but not 100% equivalent. We call such auto-correct behavior "unsafe"

We can run auto correction with the following command:

$ rubocop -a# or$ rubocop --auto-correct# or$ rubocop -A# or$ rubocop --auto-correct-all
Enter fullscreen modeExit fullscreen mode

Other RuboCop Extensions

RuboCop also has options for implementing rules on other extensions like:

Style Guide

RuboCop is based on style guides which helps in maintaining best practices for each extension. If you are curious, you can view and read guidelines from links below:

Conclusion

RuboCop is very helpful in maintaining best practices and it's one of the gem that we include in all our project setup here atTruemark.

One thing to remember with Static Code Analyzers is we have the flexibility to enable and disable rules, hence we should always discuss with the team what to include, why to include and what to disable.

This is the guide I hope I had when I was starting our as a Rails developer. I hope you find it useful!

Happy coding!

Image Credits

References

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

More fromTruemark Technology

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp