RuboCoping
RuboCop/Standard configuration with useful plugins for your project
Used 634 times
V
Vladimir Dementyev
Usage
Based on the RuboCoping with legacy post by Evil Martians.
Run this command in your Rails app directory in the terminal:
rails app:template LOCATION="https://railsbytes.com/script/V4YsLQ"
Template Source
Review the code before running this template on your machine.
say "Hey! Let's configure RuboCop for your project 🤖!\n" \
"For more information, visit https://evilmartians.com/chronicles/rubocoping-with-legacy-bring-your-ruby-code-up-to-standard"
plugins = []
base_configs = []
extensions = []
gems = []
specs = []
deps = []
ruby_version = Gem::Version.new(RUBY_VERSION).segments[0..1].join(".")
in_root do
if File.file?("Gemfile.lock")
bundler_parser = Bundler::LockfileParser.new(Bundler.read_file("Gemfile.lock"))
specs = bundler_parser.specs.map(&:name)
locked_version = bundler_parser.ruby_version.match(/(\d+\.\d+\.\d+)/)&.[](1) if bundler_parser.ruby_version
ruby_version = Gem::Version.new(locked_version).segments[0..1].join(".") if locked_version
end
end
in_root do
if File.file?("Gemfile")
bundler_parser = Bundler::Dsl.new
bundler_parser.eval_gemfile("Gemfile")
deps = bundler_parser.dependencies.map(&:name)
end
end
has_rails = ((specs | deps) & %w[activerecord actionpack rails]).any?
if has_rails && yes?("Would your like to install standard-rails? (y/n)")
plugins << "rubocop-rails"
base_configs << "standard-rails"
gems << "standard-rails"
end
has_rspec = in_root do
((specs | deps) & %w[rspec-core]).any? && File.directory?("spec")
end
if has_rspec && yes?("Would your like to install rubocop-rspec? (y/n)")
file ".rubocop/rspec.yml", ERB.new(
*[
<<~'TCODE'
require:
- rubocop-rspec
# Disable all cops by default,
# only enable those defined explcitly in this configuration file
RSpec:
Enabled: false
RSpec/Focus:
Enabled: true
RSpec/EmptyExampleGroup:
Enabled: true
RSpec/EmptyLineAfterExampleGroup:
Enabled: true
RSpec/EmptyLineAfterFinalLet:
Enabled: true
RSpec/EmptyLineAfterHook:
Enabled: true
RSpec/EmptyLineAfterSubject:
Enabled: true
RSpec/HookArgument:
Enabled: true
RSpec/HooksBeforeExamples:
Enabled: true
RSpec/ImplicitExpect:
Enabled: true
RSpec/IteratedExpectation:
Enabled: true
RSpec/LetBeforeExamples:
Enabled: true
RSpec/MissingExampleGroupArgument:
Enabled: true
RSpec/ReceiveCounts:
Enabled: true
Capybara/CurrentPathExpectation:
Enabled: true
FactoryBot/AttributeDefinedStatically:
Enabled: true
FactoryBot/CreateList:
Enabled: true
TCODE
], trim_mode: "<>").result(binding)
extensions << ".rubocop/rspec.yml"
gems << "rubocop-rspec"
end
has_minitest = in_root do
((specs | deps) & %w[minitest]).any? && File.directory?("test")
end
if has_minitest && yes?("Would your like to install rubocop-minitest? (y/n)")
file ".rubocop/minitest.yml", ERB.new(
*[
<<~'TCODE'
require:
- rubocop-minitest
TCODE
], trim_mode: "<>").result(binding)
extensions << ".rubocop/minitest.yml"
gems << "rubocop-minitest"
end
has_graphql = ((specs | deps) & %w[graphql]).any?
if has_graphql && yes?("Would your like to install rubocop-graphql? (y/n)")
file ".rubocop/graphql.yml", ERB.new(
*[
<<~'TCODE'
require:
- rubocop-graphql
TCODE
], trim_mode: "<>").result(binding)
extensions << ".rubocop/graphql.yml"
gems << "rubocop-graphql"
end
in_root do
# Final configuration generation
file ".rubocop/strict.yml", ERB.new(
*[
<<~'TCODE'
Lint/Debugger: # don't leave binding.pry
Enabled: true
Exclude: []
<% if gems.include?("rubocop-rspec") %>
RSpec/Focus: # run ALL tests on CI
Enabled: true
Exclude: []
<% end %>
<% if gems.include?("rubocop-rails") %>
Rails/Output: # Don't leave puts-debugging
Enabled: true
Exclude: []
Rails/FindEach: # each could badly affect the performance, use find_each
Enabled: true
Exclude: []
Rails/UniqBeforePluck: # uniq.pluck and not pluck.uniq
Enabled: true
Exclude: []
<% end %>
TCODE
], trim_mode: "<>").result(binding)
file ".rubocop.yml", ERB.new(
*[
<<~'TCODE'
inherit_mode:
merge:
- Exclude
require:
- standard
- standard-custom
- standard-performance
- rubocop-performance
<% plugins.each do |plugin| %>
- <%= plugin %>
<% end %>
inherit_gem:
standard: config/base.yml
standard-performance: config/base.yml
standard-custom: config/base.yml
<% base_configs.each do |plugin| %>
<%= plugin %>: config/base.yml
<% end %>
inherit_from:
<% extensions.each do |ext| %>
- <%= ext %>
<% end %>
- .rubocop/strict.yml
AllCops:
NewCops: disable
SuggestExtensions: false
TargetRubyVersion: <%= ruby_version %>
TCODE
], trim_mode: "<>").result(binding)
file "gemfiles/rubocop.gemfile", ERB.new(
*[
<<~'TCODE'
source "https://rubygems.org" do
gem "standard", "~> 1.28"
<% gems.each do |gem| %>
gem "<%= gem %>"
<% end %>
end
TCODE
], trim_mode: "<>").result(binding)
in_root do
if File.file?("Gemfile")
file "Gemfile", File.read("Gemfile") + %(\ngroup :development do\n eval_gemfile "gemfiles/rubocop.gemfile"\nend\n), force: true
end
end
has_bin_rubocop = yes?("Would your like to create a standalone RuboCop executable (bin/rubocop)? (y/n)")
if has_bin_rubocop
file "bin/rubocop", ERB.new(
*[
<<~'TCODE'
#!/bin/bash
cd $(dirname $0)/..
export BUNDLE_GEMFILE=./gemfiles/rubocop.gemfile
bundle check > /dev/null || bundle install
bundle exec rubocop $@
TCODE
], trim_mode: "<>").result(binding)
in_root { run "chmod +x bin/rubocop" }
end
end
if yes?("Would you like to generate a TODO config? (y/n)")
# First, run RuboCop and check the output
# with formatter json
in_root do
has_bin_rubocop = File.file?("bin/rubocop")
command = has_bin_rubocop ? "bin/rubocop" : "bundle exec rubocop"
output = Bundler.with_unbundled_env do
# Make sure dependencies are installed
if has_bin_rubocop
`#{command} > /dev/null`
else
run "bundle check > /dev/null || bundle install > /dev/null"
end
`#{command} --format json`
end
require "json"
summary = JSON.parse(output).dig("summary")
if summary["offense_count"] > 0
Bundler.with_unbundled_env do
# Prevent RuboCop from updating the `.rubocop.yml`
run "cp .rubocop.yml .rubocop.yml.bak"
run "#{command} " \
"--auto-gen-config " \
"--auto-gen-only-exclude " \
"--no-exclude-limit"
run "mv .rubocop.yml.bak .rubocop.yml"
end
inject_into_file ".rubocop.yml", " - .rubocop_todo.yml\n", before: " - .rubocop/strict.yml"
else
say "No offenses detected, good job! Skipping TODO generation"
end
end
end
say_status :info, "Congratulations! Your project got style! 🎉"
if yes?("Would you like to run RuboCop to check your configuration? (y/n)")
in_root do
if File.file?("bin/rubocop")
Bundler.with_unbundled_env { run "bin/rubocop" }
else
Bundler.with_unbundled_env do
run "bundle check > /dev/null || bundle install > /dev/null"
run "bundle exec rubocop"
end
end
end
end