little ruby blog

небольшой блог о ruby, rails и разной фигне

Удобная организация маршрутов в Rails-приложении

| Comments

Какая проблема?

В нашем проекте на данный момент файл маршрутов routes.rb занимает уже 180 LOC. И это совсем не предел - к концу проекта он увеличится вдвое, если не втрое. При этом, конечно, использованы все доступные на данный момент в нашей версии Rails(3.2.6) возможности организации маршрутов. В файле маршрутов я начинаю попросту путаться - довольно трудно становится найти необходимое в каше из неймспейсов, вложенных в неймспейсы. К тому же, в экране кода маршрутизации не проще разобраться, чем в любом другом экране кода.

Настало время для реорганизации и уборки!

Как решить?

Код, при помощи которого можно значительно улучшить организацию файла routes.rb, я нашел в сегодняшней рассылке rails-core. Изначально он принадлежит DHH, но я решил побродить по форкам gist’а и, как оказалось, не прогадал. В одном из форков я обнаружил по-настоящему изящное и рабочее решение, позволившее удобно реорганизовать наш routes.rb.

Суть вкратце: идеологически независимые куски маршрутизации мы выносим в другие файлы. Для их подключения мы instance_eval-им соответствующие файлы. Они выполняются в контексте текущего namespace-а.

Как это работает?

В наш routes.rb мы добавляем в самом начале (до routes.draw!) следующий код:

Дальше всё просто. В нужном месте в routes.rb мы вставляем следующий код:

1
2
3
4
5
6
SampleApp::Application.routes.draw do
  draw :routing_module_1
  namespace :namespace_1 do
    draw :routing_module_2
  end
end

И создаем в config папку routes с файлами routing_module_1.rb и namespace_1/routing_module_2.rb. В них кладём маршруты, которые будут выполняться в том контексте, в котором добавляются.

Когда создается файл маршрутов, вызывается объявленный нами выше метод draw. При вызове этого метода из namespace или scope в @scope[:path] попадает тот самый путь, в котором должны определяться подмаршруты. Если же в @scope ключ path не определён - Rails.root.join даст нам имя файла в config/routes/.

Подводные камни

Ну куда же без них-то? Подводный камень тут один, но достаточно мощный: при обычном routes.rb маршруты в окружении разработки (development) перегружаются автоматически (при помощи middleware ActionDispatch::Reloader), но поскольку отслеживаемый файл routes.rb при новом подходе не меняется - маршруты во вложенных файлах обновляться не будут, пока не будет выполнен хотя бы touch config/routes.rb, который принудительно обновит дату последнего изменения routes.rb.

К сожалению, пока не в курсе, как изменить это поведение. Если вы знаете - подскажите в комментах, пожалуйста, я дополню пост.

Comments