diff --git a/changelog/change_add_more_load_hooks_to_rails_active_support_on_load.md b/changelog/change_add_more_load_hooks_to_rails_active_support_on_load.md new file mode 100644 index 0000000000..084bae3933 --- /dev/null +++ b/changelog/change_add_more_load_hooks_to_rails_active_support_on_load.md @@ -0,0 +1 @@ +* [#1257](https://github.com/rubocop/rubocop-rails/pull/1257): Add Rails 7.1 load hooks and `active_record_sqlite3adapter` to `Rails/ActiveSupportOnLoad`. ([@earlopain][]) diff --git a/config/default.yml b/config/default.yml index 989485efa5..37291c46bf 100644 --- a/config/default.yml +++ b/config/default.yml @@ -165,6 +165,7 @@ Rails/ActiveSupportOnLoad: - 'https://guides.rubyonrails.org/engines.html#available-load-hooks' SafeAutoCorrect: false VersionAdded: '2.16' + VersionChanged: <> Rails/AddColumnIndex: Description: >- diff --git a/lib/rubocop/cop/rails/active_support_on_load.rb b/lib/rubocop/cop/rails/active_support_on_load.rb index c44b9050cd..a516586b8f 100644 --- a/lib/rubocop/cop/rails/active_support_on_load.rb +++ b/lib/rubocop/cop/rails/active_support_on_load.rb @@ -55,15 +55,35 @@ class ActiveSupportOnLoad < Base 'ActiveSupport::TestCase' => 'active_support_test_case' }.freeze + RAILS_5_2_LOAD_HOOKS = { + 'ActiveRecord::ConnectionAdapters::SQLite3Adapter' => 'active_record_sqlite3adapter' + }.freeze + + RAILS_7_1_LOAD_HOOKS = { + 'ActiveRecord::TestFixtures' => 'active_record_fixtures', + 'ActiveModel::Model' => 'active_model', + 'ActionText::EncryptedRichText' => 'action_text_encrypted_rich_text', + 'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter' => 'active_record_postgresqladapter', + 'ActiveRecord::ConnectionAdapters::Mysql2Adapter' => 'active_record_mysql2adapter', + 'ActiveRecord::ConnectionAdapters::TrilogyAdapter' => 'active_record_trilogyadapter' + }.freeze + def on_send(node) receiver, method, arguments = *node # rubocop:disable InternalAffairs/NodeDestructuring - return unless arguments && (hook = LOAD_HOOKS[receiver&.const_name]) + return unless arguments && (hook = hook_for_const(receiver&.const_name)) preferred = "ActiveSupport.on_load(:#{hook}) { #{method} #{arguments.source} }" add_offense(node, message: format(MSG, prefer: preferred, current: node.source)) do |corrector| corrector.replace(node, preferred) end end + + def hook_for_const(const_name) + hook = LOAD_HOOKS[const_name] + hook ||= RAILS_5_2_LOAD_HOOKS[const_name] if target_rails_version >= 5.2 + hook ||= RAILS_7_1_LOAD_HOOKS[const_name] if target_rails_version >= 7.1 + hook + end end end end diff --git a/spec/rubocop/cop/rails/active_support_on_load_spec.rb b/spec/rubocop/cop/rails/active_support_on_load_spec.rb index 984818aeca..cc487beb31 100644 --- a/spec/rubocop/cop/rails/active_support_on_load_spec.rb +++ b/spec/rubocop/cop/rails/active_support_on_load_spec.rb @@ -99,4 +99,47 @@ MyClass1.prepend(MyClass) RUBY end + + context 'Rails 5.2', :rails52 do + it 'registers an offense for a Rails 5.2 load hook' do + expect_offense(<<~RUBY) + ActiveRecord::ConnectionAdapters::SQLite3Adapter.include(MyClass) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `ActiveSupport.on_load(:active_record_sqlite3adapter) { include MyClass }` [...] + RUBY + + expect_correction(<<~RUBY) + ActiveSupport.on_load(:active_record_sqlite3adapter) { include MyClass } + RUBY + end + + it 'registers no offense for a Rails 7.1 load hook' do + expect_no_offenses(<<~RUBY) + ActiveRecord::TestFixtures.include(MyClass) + RUBY + end + end + + context 'Rails 7.1', :rails71 do + it 'registers an offense for a Rails 5.2 load hook' do + expect_offense(<<~RUBY) + ActiveRecord::ConnectionAdapters::SQLite3Adapter.include(MyClass) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `ActiveSupport.on_load(:active_record_sqlite3adapter) { include MyClass }` [...] + RUBY + + expect_correction(<<~RUBY) + ActiveSupport.on_load(:active_record_sqlite3adapter) { include MyClass } + RUBY + end + + it 'registers an offense for a Rails 7.1 load hook' do + expect_offense(<<~RUBY) + ActiveRecord::TestFixtures.include(MyClass) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `ActiveSupport.on_load(:active_record_fixtures) { include MyClass }` [...] + RUBY + + expect_correction(<<~RUBY) + ActiveSupport.on_load(:active_record_fixtures) { include MyClass } + RUBY + end + end end