需要建议:子菜单的Rails视图结构?

时间:2020-03-06 14:39:06  来源:igfitidea点击:

想象一下,应用程序中有两个RESTful控制器(UsersController,OffersController)和一个PagesController(用于静态内容,例如索引,关于等等)。

我们定义了以下路由:

map.with_options :controller => 'pages' do |pages|
  pages.root :action => 'index'     # static home page
  pages.about :action => 'about'    # static about page
  # maybe more static pages...
end
map.resources :users    # RESTful UsersController
map.resources :posts    # RESTful PostsController

应用程序布局如下所示:

<html>
  <head>
    <title>Demo Application</title>
  </head>
  <body>
    <ul id="menu">
       <li>
         <%= link_to 'Home', root_path %>
       </li>
       <li>
         <%= link_to 'Offers', offers_path %>
         <ul id="submenu>
           <li><%= link_to 'Search', 'path/to/search' %></li>
           <li>maybe more links...</li>
         </ul>
       </li>
       <li>
         <%= link_to 'About', about_path %>
       </li>
       <li>
         <%= link_to 'Admin', users_path %>
         <ul id="submenu">
           <li><%= link_to 'New User', new_user_path %></li>
           <li><%= link_to 'New Offer', new_offer_path %></li>
           <li>maybe more links</li>
         </ul>
       </li>
    </li>
    <%= yield %>
  </body>
</html>

布局的问题是我希望在任何时候都只可见一个#submenu。可以完全跳过所有其他子菜单(根本不需要渲染)。

以"管理"菜单为例:该菜单应对应用程序中的所有RESTful路径(" offers_path"除外)都处于活动状态。 Active表示该子菜单可见。

我能想到的唯一解决方案是在条件恶劣的情况下构建很多复杂的东西(编写和维护起来确实很复杂)。我在寻找一种优雅的解决方案?

我希望有人能理解我的问题,如果有不清楚的地方,只需评论该问题,我将对其进行详细解释。

解决方案

通常,我会抽象出菜单功能,以便有一个用于呈现"管理"菜单的助手方法。这样,有可能在帮助程序中抛出任意数量的逻辑,而不会笼罩视图逻辑。

因此,助手看起来像(原谅ruby / rails伪代码,自从我接触它以来已经有一个月或者两个月了):

def render_admin_menu()
  if !current_path.contains('offer')
    render :partial => 'shared/admin_menu'
  end
end

我们可以玩的一件事是yield和content_for,与菜单的一些部分一起使用。例如,我们可以将菜单的每个部分都放在一个部分中,然后将布局修改为以下内容:

<%= yield(:menu) %>

然后,我们可以在视图中指定content_for并将所需的任何部分放入菜单。如果未指定,则不会渲染。

<% content_for(:menu) do %>
   <%= render :partial => 'layouts/menu' %>
   <%= render :partial => 'layouts/search_menu' %>
    etc...
 <% end %>

如果在大多数页面中使用许多相同的菜单,请在布局中指定默认值(如果未找到yield(:menu))。

<%= yield(:menu) || render :partial => 'layouts/menu_default' %>

为我们节省很多打字时间。 :)我发现这是一种处理事情的好方法。