给出一个带有导航栏的布局,该导航栏取决于当前控制器:
# 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变得一团糟# 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' }
还有其他解决此问题的方法吗?您会选择哪一个?为什么?
答案 0 :(得分:1)
如果控制器可以按照其名称空间(如其导航名称)分组,那么我将采用"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
的表。该表中的条目只能从管理面板中填充。
答案 1 :(得分:0)
我走了另一条路。由于决定布局是控制器的责任,我认为这是让它也决定导航的正确方法。
因此,就像有一个“布局”声明一样,我现在有了一个“导航”声明。控制器的外观如下:
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