diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 33456fe4f5082..2fcd6359a65d1 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,7 @@ +* Add RuboCop with rules from rubocop-rails-omakase by default. Skip with --skip-rubocop. + + *DHH* and *zzak* + * Use `bin/rails runner --skip-executor` option to not wrap the runner script with an Executor. diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index fb8572ad97776..e4e14406d6fe1 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -100,6 +100,9 @@ def self.add_shared_options_for(name) class_option :skip_dev_gems, type: :boolean, default: nil, desc: "Skip development gems (e.g., web-console)" + class_option :skip_rubocop, type: :boolean, default: nil, + desc: "Skip RuboCop setup" + class_option :dev, type: :boolean, default: nil, desc: "Set up the #{name} with Gemfile pointing to your Rails checkout" @@ -379,6 +382,10 @@ def skip_propshaft? skip_asset_pipeline? || options[:asset_pipeline] != "propshaft" end + def skip_rubocop? + options[:skip_rubocop] + end + class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out) def initialize(name, version, comment, options = {}, commented_out = false) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 32e5cf7b577a9..977a7e8d5db0a 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -82,6 +82,10 @@ def dockerfiles chmod "bin/docker-entrypoint", 0755 & ~File.umask, verbose: false end + def rubocop + template "rubocop.yml", ".rubocop.yml" + end + def version_control if !options[:skip_git] && !options[:pretend] run git_init_command, capture: options[:quiet], abort_on_failure: false @@ -98,7 +102,8 @@ def app end def bin - directory "bin" do |content| + options = skip_rubocop? ? { exclude_pattern: /rubocop/ } : {} + directory "bin", **options do |content| "#{shebang}\n" + content end chmod "bin", 0755 & ~File.umask, verbose: false @@ -367,6 +372,11 @@ def create_dockerfiles build(:dockerfiles) end + def create_rubocop_file + return if skip_rubocop? + build(:rubocop) + end + def create_config_files build(:config) end diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile.tt b/railties/lib/rails/generators/rails/app/templates/Gemfile.tt index 4d16d252dc367..fe5bc553c5519 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile.tt +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile.tt @@ -40,6 +40,11 @@ end <% end -%> group :development do +<%- unless options.skip_rubocop? -%> + # Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/] + gem "rubocop-rails-omakase", require: false + +<%- end -%> <%- unless options.api? || options.skip_dev_gems? -%> # Use console on exceptions pages [https://github.com/rails/web-console] gem "web-console" diff --git a/railties/lib/rails/generators/rails/app/templates/bin/rubocop.tt b/railties/lib/rails/generators/rails/app/templates/bin/rubocop.tt new file mode 100644 index 0000000000000..81f71879712d1 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/bin/rubocop.tt @@ -0,0 +1,7 @@ +require "rubygems" +require "bundler/setup" + +# explicit rubocop config increases performance slightly while avoiding config confusion. +ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__)) + +load Gem.bin_path("rubocop", "rubocop") diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/application.rb.tt index 6d059aa757d74..e0eda6e324428 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb.tt @@ -18,7 +18,7 @@ module <%= app_const_base %> # Please, add to the `ignore` list any other `lib` subdirectories that do # not contain `.rb` files, or that should not be reloaded or eager loaded. # Common ones are `templates`, `generators`, or `middleware`, for example. - config.autoload_lib(ignore: %w(assets tasks)) + config.autoload_lib(ignore: %w[assets tasks]) # Configuration for the application, engines, and railties goes here. # diff --git a/railties/lib/rails/generators/rails/app/templates/rubocop.yml.tt b/railties/lib/rails/generators/rails/app/templates/rubocop.yml.tt new file mode 100644 index 0000000000000..f9d86d4a54802 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/rubocop.yml.tt @@ -0,0 +1,8 @@ +# Omakase Ruby styling for Rails +inherit_gem: { rubocop-rails-omakase: rubocop.yml } + +# Overwrite or add rules to create your own house style +# +# # Use `[a, [b, c]]` not `[ a, [ b, c ] ]` +# Layout/SpaceInsideArrayLiteralBrackets: +# Enabled: false diff --git a/railties/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt b/railties/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt index d19212abd5ced..d7e6bba8af7ba 100644 --- a/railties/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt @@ -1,5 +1,5 @@ require "test_helper" class ApplicationSystemTestCase < ActionDispatch::SystemTestCase - driven_by :selenium, using: :chrome, screen_size: [1400, 1400] + driven_by :selenium, using: :chrome, screen_size: [ 1400, 1400 ] end diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 09e01bf4208af..ebaeccd7aa75a 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -8,6 +8,7 @@ .gitattributes .gitignore .dockerignore + .rubocop.yml .ruby-version README.md Gemfile @@ -39,6 +40,7 @@ bin/docker-entrypoint bin/rails bin/rake + bin/rubocop bin/setup config/application.rb config/boot.rb @@ -623,6 +625,19 @@ def test_inclusion_of_a_debugger end end + def test_inclusion_of_rubocop + run_generator + assert_gem "rubocop-rails-omakase" + end + + def test_rubocop_is_skipped_if_required + run_generator [destination_root, "--skip-rubocop"] + + assert_no_gem "rubocop" + assert_no_file "bin/rubocop" + assert_no_file ".rubocop.yml" + end + def test_usage_read_from_file assert_called(File, :read, returns: "USAGE FROM FILE") do assert_equal "USAGE FROM FILE", Rails::Generators::AppGenerator.desc