Rails 4: split routes.rb в несколько файлов меньшего размера

Я хотел бы разбить маршруты в приложении rails 4. Для рельсов 3 на вопрос был дан ответ несколько раз:

Каким будет правильный способ сделать это в rails 4 +, как получить контроль над порядком загрузки маршрутов?

Предлагаемый из рельсов 3 вопроса:

application.rb

    config.paths['config/routes'] = Dir["config/routes/*.rb"]

Сбой:

/Users/jordan/.rvm/gems/[email protected]/gems/railties-4.0.0/lib/rails/application/routes_reloader.rb:10:in `rescue in execute_if_updated ': Rails:: Application:: RoutesReloader # execute_if_updated делегировано updater.execute_if_updated, но updater равен нулю:

@route_sets = [#] > (RuntimeError)

Ответы

Ответ 1

Это было удалено из Rails 4 в июне 2012 года. 5e7d6bba возвращает предыдущую фиксацию, удаляя поддержку для загрузки нескольких внешних файлов маршрутов в качестве часть config.rb.

Для дальнейшего ознакомления ознакомьтесь с комментариями к этому commit.

Ответ 2

Я справился так:

# config/application.rb
config.autoload_paths << Rails.root.join('config/routes')

# config/routes.rb
Rails.application.routes.draw do
  root to: 'home#index'

  extend ApiRoutes
end

# config/routes/api_routes.rb
module ApiRoutes
  def self.extended(router)
    router.instance_exec do
      namespace :api do
        resources :tasks, only: [:index, :show]
      end
    end
  end
end

Здесь я добавил каталог config/routes для модулей автозагрузки, определенных в нем. Это обеспечит перезагрузку маршрутов при изменении этих файлов.

Используйте extend, чтобы включить эти модули в основной файл (они будут автоматически загружены, не нужно их требовать).

Используйте instance_exec внутри self.extended для рисования маршрутов в контексте маршрутизатора.

Ответ 3

Немного поздно для вечеринки, но вы можете сделать это в Rails 4 обезьяной, исправляющей картупер вверху вашего файла route.rb. то есть:

# config/routes.rb
class ActionDispatch::Routing::Mapper
  def draw(routes_name)
    instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb")))
  end
end

И затем с помощью метода draw в routes.rb с:

Rails.application.routes.draw do
  draw :api
end

Это ожидает файл в config/routes/api.rb.

Немного более полное объяснение с примерами разделения файла маршрутов здесь.

Ответ 4

Мне не нравятся ранее опубликованные решения - расширения с помощью мартышек-патчей - поскольку они тоже:

  1. прервать ООП (File.read + instance_eval - крипы) или
  2. запретить повторное использование: включая модули - вы можете сделать это только один раз - не берите в голову, что на втором вы понимаете, что включение модуля на самом деле является механизмом для выполнения небольшого количества кода, крипы

мы больше не находимся в 2000-х, недопустимо перемещать части исходных файлов и File.read - instance_eval их, а затем задаться вопросом, что произошло - или включить модули в качестве вызова функции бедного человека - если есть любая альтернатива.

Я делаю это, обратите внимание, что это гнездо:

scope :processing do
  SomeModule::SomeDomain::Routes.call(self)
end

# and it reusable:
scope :some_other_scope do
  SomeModule::SomeDomain::Routes.call(self)
end

Преимущество этого подхода заключается в том, что в конечном итоге он представляет собой простой исполняемый код ruby, который может быть легко перемещен и понят как вашей IDE, так и вашими коллегами-программистами.

Вы найдете вышеупомянутый фрагмент кода в routes.rb, посмотрите на него, щелкните его, удерживая клавишу , и вы обнаружите, что ожидали:

module SomeModule::SomeDomain
  class Routes
    def self.call r
      r.scope :some_scope do
        r.match .....
    end
  end
end

это означает, что это чистый код.

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

PS

Я также использую модуль module, который делает класс кряком похожим на функцию - допускает компоновку с процессорами и многое другое - но в этом нет особой необходимости, он просто даст вам синтаксическую конфету высказывания SomeModule::SomeDomain::Routes[self]