仅导航取决于控制器时可用的布局方法

时间:2019-02-07 23:30:16

标签: ruby-on-rails partials

给出一个带有导航栏的布局,该导航栏取决于当前控制器:

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

该应用程序具有多个业务领域,比如说“客户”,“任务”,“书籍”,以及各自不同的导航(clients_navtasks_navbooks_nav)。

每个部分都有多个控制器,该视图将显示基于控制器业务域的导航(例如,Clients :: CompaniesController将显示clients_nav)。

上面的html被简化了,但基本上,所有控制器都共享相同的布局,除了domain_nav取决于域。

我看到几种解决方法:

  • 使用助手,并根据控制器确定要使用的导航 名称:这意味着每次新控制器被创建时都要编辑助手 介绍,感觉不对
  • 在每个视图中分别使用content_for :navigationyield :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' }

还有其他解决此问题的方法吗?您会选择哪一个?为什么?

2 个答案:

答案 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