diff --git a/changelog/new_add_new_rails_to_formatted_s_cop.md b/changelog/new_add_new_rails_to_formatted_s_cop.md new file mode 100644 index 0000000000..1998d56ad2 --- /dev/null +++ b/changelog/new_add_new_rails_to_formatted_s_cop.md @@ -0,0 +1 @@ +* [#691](https://github.com/rubocop/rubocop-rails/pull/691): Add new `Rails/ToFormattedS` cop. ([@koic][]) diff --git a/config/default.yml b/config/default.yml index ee8fa92ae4..e73f9af002 100644 --- a/config/default.yml +++ b/config/default.yml @@ -905,6 +905,16 @@ Rails/TimeZoneAssignment: - spec/**/*.rb - test/**/*.rb +Rails/ToFormattedS: + Description: 'Checks for consistent uses of `to_fs` or `to_formatted_s`.' + StyleGuide: 'https://rails.rubystyle.guide/#prefer-to-fs' + Enabled: pending + EnforcedStyle: to_fs + SupportedStyles: + - to_fs + - to_formatted_s + VersionAdded: '<>' + Rails/TransactionExitStatement: Description: 'Avoid the usage of `return`, `break` and `throw` in transaction blocks.' Enabled: pending diff --git a/lib/rubocop/cop/rails/to_formatted_s.rb b/lib/rubocop/cop/rails/to_formatted_s.rb new file mode 100644 index 0000000000..96e2580327 --- /dev/null +++ b/lib/rubocop/cop/rails/to_formatted_s.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Rails + # This cop checks for consistent uses of `to_fs` or `to_formatted_s`, + # depending on the cop's configuration. + # + # @example EnforcedStyle: to_fs (default) + # + # # bad + # time.to_formatted_s(:db) + # + # # good + # time.to_fs(:db) + # + # @example EnforcedStyle: to_formatted_s + # + # # bad + # time.to_fs(:db) + # + # # good + # time.to_formatted_s(:db) + # + class ToFormattedS < Base + include ConfigurableEnforcedStyle + extend AutoCorrector + extend TargetRailsVersion + + minimum_target_rails_version 7.0 + + MSG = 'Use `%s` instead.' + RESTRICT_ON_SEND = %i[to_formatted_s to_fs].freeze + + def on_send(node) + return if node.method?(style) + + add_offense(node.loc.selector, message: format(MSG, prefer: style)) do |corrector| + corrector.replace(node.loc.selector, style) + end + end + end + end + end +end diff --git a/lib/rubocop/cop/rails_cops.rb b/lib/rubocop/cop/rails_cops.rb index 0615c7a2f9..2d3a80d544 100644 --- a/lib/rubocop/cop/rails_cops.rb +++ b/lib/rubocop/cop/rails_cops.rb @@ -107,6 +107,7 @@ require_relative 'rails/table_name_assignment' require_relative 'rails/time_zone' require_relative 'rails/time_zone_assignment' +require_relative 'rails/to_formatted_s' require_relative 'rails/transaction_exit_statement' require_relative 'rails/uniq_before_pluck' require_relative 'rails/unique_validation_without_index' diff --git a/spec/rubocop/cop/rails/to_formatted_s_spec.rb b/spec/rubocop/cop/rails/to_formatted_s_spec.rb new file mode 100644 index 0000000000..b01d986884 --- /dev/null +++ b/spec/rubocop/cop/rails/to_formatted_s_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +RSpec.describe RuboCop::Cop::Rails::ToFormattedS, :config do + context 'Rails >= 7.0', :rails70 do + context 'EnforcedStyle: to_fs' do + let(:cop_config) { { 'EnforcedStyle' => 'to_fs' } } + + it 'registers and corrects an offense when using `to_formatted_s`' do + expect_offense(<<~RUBY) + time.to_formatted_s(:db) + ^^^^^^^^^^^^^^ Use `to_fs` instead. + RUBY + + expect_correction(<<~RUBY) + time.to_fs(:db) + RUBY + end + + it 'does not register an offense when using `to_fs`' do + expect_no_offenses(<<~RUBY) + time.to_fs(:db) + RUBY + end + end + + context 'EnforcedStyle: to_formatted_s' do + let(:cop_config) { { 'EnforcedStyle' => 'to_formatted_s' } } + + it 'registers and corrects an offense when using `to_fs`' do + expect_offense(<<~RUBY) + time.to_fs(:db) + ^^^^^ Use `to_formatted_s` instead. + RUBY + + expect_correction(<<~RUBY) + time.to_formatted_s(:db) + RUBY + end + + it 'does not register an offense when using `to_formatted_s`' do + expect_no_offenses(<<~RUBY) + time.to_formatted_s(:db) + RUBY + end + end + end + + context 'Rails <= 6.1', :rails61 do + context 'EnforcedStyle: to_fs' do + let(:cop_config) { { 'EnforcedStyle' => 'to_fs' } } + + it 'does not register an offense when using `to_formatted_s`' do + expect_no_offenses(<<~RUBY) + time.to_formatted_s(:db) + RUBY + end + end + + context 'EnforcedStyle: to_formatted_s' do + let(:cop_config) { { 'EnforcedStyle' => 'to_formatted_s' } } + + it 'does not register an offense when using `to_fs`' do + expect_no_offenses(<<~RUBY) + time.to_fs(:db) + RUBY + end + end + end +end diff --git a/spec/support/shared_contexts.rb b/spec/support/shared_contexts.rb index aac0827c53..f6eddb00ee 100644 --- a/spec/support/shared_contexts.rb +++ b/spec/support/shared_contexts.rb @@ -23,3 +23,7 @@ RSpec.shared_context 'with Rails 6.1', :rails61 do let(:rails_version) { 6.1 } end + +RSpec.shared_context 'with Rails 7.0', :rails70 do + let(:rails_version) { 7.0 } +end