当只有导航依赖于控制器时可用的布局方法
Available approaches for layouts when only the navigation depends on the controller
给定一个带有依赖于当前控制器的导航栏的布局:
# layout.html.slim
doctype html
html
body
main
= render partial: 'domain_nav'
= yield
该应用有多个业务领域,比方说 "Clients"、"Tasks"、"Books",它们有自己独特的导航(clients_nav
、tasks_nav
、 books_nav
)。
每个部分都有多个控制器,视图会根据控制器业务域显示导航(例如Clients::CompaniesController会显示clients_nav
)。
上面的 html 是简化的,但基本上,所有控制器共享相同的布局,除了 domain_nav
取决于域。
我看到了几种处理方法:
- 使用助手并根据控制器确定使用哪个导航
name :这意味着每次新控制器出现时编辑助手
介绍过,感觉不太对
- 在每个视图中使用
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' }
还有其他方法可以解决这个问题吗?你会选择哪一个,为什么?
如果控制器可以像导航名称一样按命名空间分组,我将采用 "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
如果您不能按这样的名称空间对控制器进行分组,那么只有在您有管理面板的情况下,您仍然可以采用这种方法的不同变体。我们可以创建一个 table,将 controller_name
映射到 navigation_path
。此 table 上的条目只能从管理面板填充。
我走了一条不同的路。由于控制器有责任决定布局,我认为 rails 让它也决定导航的方式。
就像有一个 "layout" 声明一样,我现在有一个 "navigation" 声明。控制器的外观如下:
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
给定一个带有依赖于当前控制器的导航栏的布局:
# layout.html.slim
doctype html
html
body
main
= render partial: 'domain_nav'
= yield
该应用有多个业务领域,比方说 "Clients"、"Tasks"、"Books",它们有自己独特的导航(clients_nav
、tasks_nav
、 books_nav
)。
每个部分都有多个控制器,视图会根据控制器业务域显示导航(例如Clients::CompaniesController会显示clients_nav
)。
上面的 html 是简化的,但基本上,所有控制器共享相同的布局,除了 domain_nav
取决于域。
我看到了几种处理方法:
- 使用助手并根据控制器确定使用哪个导航 name :这意味着每次新控制器出现时编辑助手 介绍过,感觉不太对
- 在每个视图中使用
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' }
还有其他方法可以解决这个问题吗?你会选择哪一个,为什么?
如果控制器可以像导航名称一样按命名空间分组,我将采用 "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
如果您不能按这样的名称空间对控制器进行分组,那么只有在您有管理面板的情况下,您仍然可以采用这种方法的不同变体。我们可以创建一个 table,将 controller_name
映射到 navigation_path
。此 table 上的条目只能从管理面板填充。
我走了一条不同的路。由于控制器有责任决定布局,我认为 rails 让它也决定导航的方式。
就像有一个 "layout" 声明一样,我现在有一个 "navigation" 声明。控制器的外观如下:
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