Автоматическое преобразование вложенных классов в компактный стиль в Ruby - PullRequest
1 голос
/ 17 января 2020

У меня очень большая кодовая база, которая использует сочетание вложенных и компактных стилей для определений классов.

RuboCop: ClassAndModuleChildren

# Nested
class Foo
  class Bar
  end
end

# Compact
class Foo::Bar
end

Я строю автоматизированный инструмент, который использует регулярные выражения для реорганизации пространств имен большого числа классов. Это легко сделать, когда определения классов представлены в компактном формате, но гораздо сложнее, когда они находятся во вложенном формате.

Поэтому мне нужен способ преобразовать все экземпляры вложенного стиля в компактный. style.

Я надеялся, что RuboCop сможет сделать это для меня, и хотя docs , похоже, предполагает, что он поддерживает автозамену, я не могу заставить его работать. RuboCop сообщает о нарушениях, но не исправляет их.

bundle exec rubocop --auto-correct app/controllers/announcements_controller.rb
Inspecting 1 file
C

Offenses:

app/controllers/announcements_controller.rb:1:8: C: Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
module Vapid
       ^^^^^
app/controllers/announcements_controller.rb:2:10: C: Style/ClassAndModuleChildren: Use compact module/class definition instead of nested style.
  module V2
         ^^

1 file inspected, 2 offenses detected

Буду признателен, если кто-то сможет выполнить эту работу или знает лучший способ автоматически принять компактный стиль.

1 Ответ

2 голосов
/ 17 января 2020

Простой ответ: не делайте этого . Вы (и тот, кто написал этого полицейского) ошибочно предполагаете, что два «стиля» на самом деле делают одно и то же. Они не Последнее считается очень плохой практикой.

Определение (и повторное открытие) пространственных имен классов и модулей с использованием явного вложения. Использование оператора разрешения области действия может привести к неожиданным постоянным поискам из-за лексической области видимости Ruby, которая зависит от вложенности модуля в точке определения.
- Руководство по стилю Ruby

Итак, допустим, у вас есть:

module Foo
  TEST = "I'm nested in Foo"
end

module Foo
  class Bar
    puts TEST
  end
end

Это установит I'm nested in Foo, поскольку TEST разрешено до Foo::TEST. Давайте изменим определение класса, чтобы использовать оператор разрешения области:

TEST = "I'm in the global scope"

module Foo
  TEST = "I'm nested in Foo"
end

class Foo::Bar
  puts TEST
end

Это установит I'm in the global scope. Поскольку вложение модуля по-прежнему является глобальной областью действия, а TEST разрешается в ::TEST. Ваше небольшое «улучшение» фактически сломает любой код, который зависит от правильного вложения модуля.

...