Skip to content

Commit

Permalink
[Fix rubocop#664] Fix a false positive for Rails/MigrationClassName
Browse files Browse the repository at this point in the history
… cop

Fixes rubocop#664.

This PR fixes a false positive for `Rails/MigrationClassName` when
`ActiveSupport::Inflector` is applied to the class name and the case
is different.

Occasionally user want to treat a word like `Oauth` as` OAuth`.
This PR is case insensitive for comparisons between migration class name
and filename. It's may not a big deal because it's based on filename.
  • Loading branch information
koic committed Mar 16, 2022
1 parent 8373c5a commit 0e5a962
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#664](https://github.com/rubocop/rubocop-rails/issues/664): Fix a false positive for `Rails/MigrationClassName` when `ActiveSupport::Inflector` is applied to the class name and the case is different. ([@koic][])
30 changes: 11 additions & 19 deletions lib/rubocop/cop/rails/migration_class_name.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,30 @@ class MigrationClassName < Base
extend AutoCorrector
include MigrationsHelper

MSG = 'Replace with `%<corrected_class_name>s` that matches the file name.'
MSG = 'Replace with `%<camelized_basename>s` that matches the file name.'

def on_class(node)
return if in_migration?(node)

snake_class_name = to_snakecase(node.identifier.source)
basename = basename_without_timestamp_and_suffix(processed_source.file_path)

basename = basename_without_timestamp_and_suffix
return if snake_class_name == basename
class_identifier = node.identifier
camelized_basename = camelize(basename)
return if class_identifier.source.casecmp(camelized_basename).zero?

corrected_class_name = to_camelcase(basename)
message = format(MSG, corrected_class_name: corrected_class_name)
message = format(MSG, camelized_basename: camelized_basename)

add_offense(node.identifier, message: message) do |corrector|
corrector.replace(node.identifier, corrected_class_name)
add_offense(class_identifier, message: message) do |corrector|
corrector.replace(class_identifier, camelized_basename)
end
end

private

def basename_without_timestamp_and_suffix
filepath = processed_source.file_path
def basename_without_timestamp_and_suffix(filepath)
basename = File.basename(filepath, '.rb')
basename = remove_gem_suffix(basename)

basename.sub(/\A\d+_/, '')
end

Expand All @@ -54,17 +54,9 @@ def remove_gem_suffix(file_name)
file_name.sub(/\..+\z/, '')
end

def to_camelcase(word)
def camelize(word)
word.split('_').map(&:capitalize).join
end

def to_snakecase(word)
word
.gsub(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
.tr('-', '_')
.downcase
end
end
end
end
Expand Down
19 changes: 19 additions & 0 deletions spec/rubocop/cop/rails/migration_class_name_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,23 @@ class AddBlobs < ActiveRecord::Migration[7.0]
RUBY
end
end

#
# When `OAuth` is applied instead of `Oauth` for `oauth`.
#
# # config/initializers/inflections.rb
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym 'OAuth'
# end
#
context 'when `ActiveSupport::Inflector` is applied to the class name and the case is different' do
let(:filename) { 'db/migrate/20210623095243_remove_unused_oauth_scope_grants.rb' }

it 'does not register an offense' do
expect_no_offenses(<<~RUBY, filename)
class RemoveUnusedOAuthScopeGrants < ActiveRecord::Migration[7.0]
end
RUBY
end
end
end

0 comments on commit 0e5a962

Please sign in to comment.