基于控制器切换布局列

时间:2012-01-16 20:06:33

标签: ruby-on-rails ruby-on-rails-3 templates inheritance erb

基本上我的应用程序看起来像这样

<!DOCTYPE html>
<html>
<head>
    ...
</head>
<body>
<div id="content">
    <div id="content_left">
        // Some Stuff
    </div>

    <div id="content_right">
        <%= yield %>
    </div>
</div>
</body>
</html>

现在我想在基于控制器的两列布局和单列布局之间切换(最好:也基于我正在使用的方法)。

在正文和内容之间以及在头部中有太多东西可以简单地创建第二个布局并将其作为layout调用添加到我的控制器中而不需要太多的代码重复。

我喜欢做的事情是这样的:

所有人都应该使用这个

<!DOCTYPE html>
<html>
<head>
    ...
</head>
<body>
 // much stuff
 <%= yield %>
</body>
</html>

现在我可以在两个布局之间切换,f.e

single_col

<div id="content">
    <%= yield %>
</div>

或two_column

<div id="content">
    <div id="content_left">
        // Some Stuff
    </div>

    <div id="content_right">
        <%= yield %>
    </div>
</div>

然后在最后一个yield中应该有与我的控制器和方法相关的视图。

有一种简单的方法可以达到这个目的吗?

感谢所有提示。

如果不清楚,请发表评论。

8 个答案:

答案 0 :(得分:2)

将布局的不同部分放在部分中!然后根据内容渲染部分 params[:controller]params[:action]。例如:

<% if params[:controller] == "controller_name" %>
     <%= render 'partial_name1' %>
<% else %>
     <%= render 'partial_name2' %>
<% end %>

params[:controller]params[:action]始终可用!这是一个向您展示其工作原理的示例。因为在视图中也不存在任何逻辑!

答案 1 :(得分:1)

您可以使用两种布局,这两种布局都会呈现包含两者共有内容的页眉和页脚部分。

或者,您使用&lt;%= yield:sidebar%&gt;然后注入一些东西

<% content_for(:sidebar) do %>
  some stuff here
<% end %>

Take a look at Rails guide section about those here.

答案 2 :(得分:1)

我认为你正在寻找一种方法来使用内部有两个子布局的共享布局,在这里你可以:

将此添加到您的application_helper.rb

  # Allows easy using nested layouts
  def inside_layout(layout = 'application', &block)
    render :inline => capture_haml(&block), :layout => "layouts/#{layout}"
  end

布局/ application.html.haml

!!!
%html
  %head
    -# your header content
  %body
    .content
      = yield

布局/ single_column.html.haml

= inside_layout do
  .middle
    = yield        

布局/ two_column.html.haml

= inside_layout do
  .left
    -# your shared left content
  .right
    = yield        

现在可以像普通布局一样使用列布局,因此您只需在控制器中设置它们

即可
layout "single_column"

注意:所有标记都在HAML宝石中,我可以强烈建议。

希望它有所帮助:)

答案 3 :(得分:0)

您可以在rails项目中使用多个布局。你可以有一个2列和一个列。

要指定使用的布局,请在控制器的方法中提供。

def index
  respond_to do |format|
    if current_user
      format.html {render 'pages/index', :layout => 'home'}# index.html.erb
    else
      format.html {render 'pages/landingpage', :layout => 'landingpage'}# index.html.erb
    end
  end
end

例如,上面的控制器将根据index.html.erb的值呈现视图landingpage.html.erbcurrent_user。您也只能将布局参数提供给render,如render :layout => 'home'

您还可以查看nested layouts,但我从未与这些人合作过。

答案 4 :(得分:0)

您可以使用sub_layouts

Class IndexController < ApplicationController

  def index

    def sub_layout
      "left"
    end

   end

 end

将子布局添加到/app/view/shared/layouts/sub/_mysublayout.haml或.erb

在/app/views/layouts/application.haml/.erb *您的主要布局文件*

= render:partial =&gt;“layouts / sub /#{controller.sub_layout}”

通过一些检查nils with rescue nil你可以让这个子模板加载布局,比如说右边或左边的col,在我的应用程序中使用它有很大的好处。它节省了大量时间,并为您提供了在动作基础上设置布局的额外灵活性。

答案 5 :(得分:0)

我假设您的单列布局中没有content_left的信息。
在两列布局中,您可以获得content_leftcontent_right的信息。
有很多方法,但我推荐的东西完全由CSS控制

CSS类将如下所示

#content_left{
    float: left;
    background-color: red;
}
#content_right{
        background-color: green;
}
#content {
    margin: 0 auto;
    width: 80%;
}

现在请注意......如果content_left div为空,则content_right div将扩展为全宽。您已准备好使用单列布局。如果您在content_left中有数据,则会相应显示。

答案 6 :(得分:0)

我正在使用辅助方法设置动态侧边栏,您可以根据自己的要求使用。

<div id="main_content" class="<%= main_content_css_class %>">
   <%= yield %>
</div>
<div id="sidebar" class="<%= sidebar_css_class %>">
  <%= yield :sidebar %>
</div>

在助手

def sidebar_enabled?
 current_page = "#{controller.controller_name}.#{controller.action_name}"
 current_controller = controller.controller_name
 pages = %w(home)
 return pages.include?(current_page) || pages.include?(current_controller)

end

def main_content_css_class
  sidebar_enabled? ? "grid_12" : "grid_16"
end

# Returns the CSS class for the 'sidebar' div depending on sidebar requirement
def sidebar_css_class
   sidebar_enabled? ? "grid_4" : "dont-show"
end 

使用您的代码也更清晰,更易于维护。

答案 7 :(得分:0)

我通常将类放在控制器和操作名称的body元素上,因为它在很多方面都很方便。以下是基于该策略的示例:

...
<body class="<%= controller_name %> <%= action_name %>">
<div id="content">
    <div id="sidebar">
        // Some Stuff
    </div>

    <div id="main">
        <%= yield %>
    </div>
</div>
</body>
...

然后是获得正确的CSS的问题。如果你有一个“帖子”控制器,边栏通常是可见的,你想隐藏它:

body.posts { #sidebar { display: none; } };

如果您希望它有时只显示,您可以反转逻辑,使其通常隐藏,然后覆盖更具体的范围来显示它。或者,您可以在所有“索引”操作上添加一列,为其他所有操作添加两列,等等。

对此的不利之处在于,您的视图与控制器的名称相关联并不是无关紧要的。即这种策略违反了“告诉,不要问”的原则。我仍然认为这是值得的,因为我还没有受到涉及此代码的令人讨厌的重构。通常,只需在ex中更改控制器名称的几个实例即可。重命名文件时“posts.css.scss”;没什么大不了。只是要权衡一下。

另外,请注意我选择了更多描述性的类名。正如你的例子所示,“左”和“右”是短暂的。 “补充工具栏”和“主要”可能不是您所拥有的,但我会尽可能地描述其中的内容。