Как определить вложенный контроллер для работы с автозагрузчиком Rails? - PullRequest
1 голос
/ 08 ноября 2019

Скажем, у меня есть два стандартных ресурса рельсов, определенных как контроллеры, каждый со своими собственными действиями CRUD (index, show и т. Д.)

  • EmployeesController
  • Employees::AssignmentController

Каталог выглядит так -

app/
  controllers/
    - employees_controller.rb
    employees/
      - assignment_controller.rb

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

Вариант A - Константа в пространстве имен

Если я это сделаю -

class Employees::AssignmentController < ApplicationController
  ...
end

В журнале приложений и при выполнении интеграционных тестов я получаю следующую ошибку:

LoadError: Unable to autoload constant Employees::AssignmentController, expected /Users/jeeves/git/my-project/app/controllers/employees/assignment_controller.rb to define it>

Не нравится константа, определенная как одно пространство имен - Employees::AssignmentController

Опция B - Вложенная константа внутри модуля

Если я это сделаю -

module Employees
  class AssignmentController < ApplicationController
  end
end

Я на самом деле получаю ту же ошибку LoadError, что и выше.

Вариант C - Вложенная константа внутри класса

Наконец, если я это сделаю -

class Employees
  class AssignmentController < ApplicationController
  end
end

Я получу TypeError: Employees is not a class, что имеет смысл, поскольку внешний classне определеноЯ пытаюсь исправить это, добавив явное определение class с пустым файлом

 app/
   controllers/
     - employees_controller.rb
+    - employees.rb
     employees/
       - assignment_controller.rb
class Employees
end

И это работает. Но глупо, что этот дополнительный фиктивный файл висит в app/controllers, особенно когда речь идет даже не о самом контроллере.

Вопрос

Существует ли правильный способ решения вышеуказанной ситуации? Вариант С мой единственный вариант? Правильно ли я использую пространства имен или мне следует избегать их всех вместе?

Спасибо!

1 Ответ

1 голос
/ 08 ноября 2019

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

Примером такого удивительного поведения является:

class Employees::AssignmentController
  def index
    @rate = Rate.find(...)
  end
end

Можно ожидать, что Rate будет разрешена как Employees::Rate, но на самом деле она разрешена до ::Rate, поскольку лексическая область действия ::.

Это предпочтительный метод:

module Employees
  class AssignmentController
    def index
      @rate = Rate.find(...) # resolves to Employees::Rate
    end
  end
end

Повторно открывает модуль и определяет новую константу в правильной лексической области.

Что касается альтернативы C - это возможно, поскольку классы в Rubyявляются модулями (отметьте Class.ancestors, если вы не верите мне), но это не считается хорошей формой, поскольку классы должны быть вещами, которые могут быть созданы.

Генераторы rails делают это «неправильным» способом, используяОператор разрешения области видимости, но это на самом деле только из-за ограничений в системе шаблонов файлов.

Тогда почему я получаю ошибку загрузки?

Я не активируюсоюзник знает. Это предпочтительный метод, и нет никаких очевидных причин, почему он не работает в этом случае. Дважды проверьте все. Перезагрузите пружину, запустив spring stop и перезагрузите сервер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...