RuboCoping
RuboCop/Standard configuration with useful plugins for your project
Used 857 times
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