Доступны подходы для макетов, когда от контроллера зависит только навигация - PullRequest
0 голосов
/ 08 февраля 2019

Учитывая макет с панелью навигации, которая зависит от текущего контроллера:

# layout.html.slim
doctype html
html
  body
    main
      = render partial: 'domain_nav'
      = yield

Приложение имеет несколько бизнес-доменов, скажем, «Клиенты», «Задачи», «Книги», со своими собственнымиразличные навигации (clients_nav, tasks_nav, books_nav).

Каждая часть имеет несколько контроллеров, и представление будет отображать навигацию, основанную на бизнес-области контроллера (например, Clients :: CompaniesController будет отображать clients_nav).

Приведенный выше HTML-кодупрощенно, но в основном все контроллеры имеют одну и ту же компоновку, кроме domain_nav, который зависит от домена.

Я вижу несколько способов справиться с этим:

  • использовать помощника и определитькакую навигацию использовать на основе имени контроллера: это означает, что редактирование помощника происходит каждый раз, когда вводится новый контроллер, это не правильно
  • использовать content_for :navigation в каждом представлении и yield :navigation: так как мы 'Убедитесь, что навигация отображается для каждого вида, это тоже не правильно
  • использовать подкомпоновку для раздела и вызывать render layout: 'clients/layout' do: это работает, но тогда i18n превращается в беспорядок
  • определить одну раскладку для домена: не очень СУХОЙ
  • использовать одну раскладку и определить, какую навигацию (частичное имя) использовать в контроллере: это частичное имя будет установлено с помощью usiМожно указать либо наследование (иметь один контроллер на домен, который задает частичное имя nav), либо проблемы
  • определить макет для домена (настройка макета в каждом контроллере), но отобразить их, используя общий макет, как показано ниже

# layouts/_shared.html.slim
doctype html
html
  body
    main
      = render partial: nav_path
      = yield

# layouts/clients.html.slim
= render partial: 'layouts/shared', locals: { nav_path: 'clients/nav' }

# layouts/tasks.html.slim
= render partial: 'layouts/shared', locals: { nav_path: 'tasks/nav' }

# layouts/books.html.slim
= render partial: 'layouts/shared', locals: { nav_path: 'books/nav' }

Есть ли другие подходы к этой проблеме?Какой бы вы выбрали и почему?

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

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

Так же, как есть объявление "layout", у меня теперь есть«навигационная» декларация.Вот как выглядят контроллеры:

class ClientsController < ApplicationController
  navigation 'clients/nav'
  …
end

class BooksController < ApplicationController
  navigation 'books/nav'
  …
end

, и у меня есть только один макет:

doctype html
html
  body
    main
      = render partial: navigation
      = yield

Метод навигации объявлен в ApplicationController:

class ApplicationController < ActionController::Base
  helper_method :navigation

  def self.navigation(path)
    define_method :navigation do
      path
    end
  end
end
0 голосов
/ 08 февраля 2019

Если контроллеры можно сгруппировать по их пространству имен так же, как по имени навигации, я пойду с подходом "use a helper and determine which nav to use based on the controller name".Например, если имя контроллера начинается с Clients (например, Clients::CompaniesController), мы можем легко сопоставить его с clients_nav.

def nav_path
    if params[:controller].starts_with? "Client"
        'clients/nav'
    elsif params[:controller].starts_with? "Task"
        'tasks/nav'
    else
        'books/nav'
    end
end

Если вы не можете группировать контроллеры по такому пространству имен, вы все равно можете перейтис другим вариантом этого подхода, только если у вас есть панель администратора.Мы могли бы создать таблицу, которая отображается от controller_name до navigation_path.Записи в этой таблице могут быть заполнены только из панели администратора.

...