每个动作的Rails布局?


165

对于某些操作,我使用了不同的布局(大多数情况下,对于大多数控制器中的新操作)。

我想知道指定布局的最佳方法是什么?(我在同一控制器中使用3个或更多不同的布局)

我不喜欢使用

渲染:布局=>'名称'

我喜欢做

布局“名称”,:only => [:new]

但是我不能用它来指定2个或更多不同的布局。

例如:

当我在同一控制器中使用不同的布局名称和唯一的选项在同一控制器中调用布局两次时,第一个将被忽略-这些动作不会显示在我指定的布局中。

注意:我正在使用Rails 2。


1
Rails的指南文档:guides.rubyonrails.org/...
凯文-

1
好点子。Rails 2的文档:guides.rubyonrails.org/v2.3.11/…– 2014
凯文

2
(此外,我发布了该指南以帮助将来的读者。毫无疑问,您早已解决了您的问题;-)
凯文

Answers:


297

您可以使用一种方法来设置布局。

class MyController < ApplicationController
  layout :resolve_layout

  # ...

  private

  def resolve_layout
    case action_name
    when "new", "create"
      "some_layout"
    when "index"
      "other_layout"
    else
      "application"
    end
  end
end

22
太好了,谢谢。如果有人想用单线做简单的事情,那么以下是可能的。它易于阅读并将其放置在控制器顶部。---layout Proc.new{ ['index', 'new', 'create'].include?(action_name) ? 'some_layout' : 'other_layout' }
霍利2011年

1
如果各种布局分别使用多个不同的css和js文件,这会对应用程序性能产生很大影响吗?
Noz 2012年

15
-1:太复杂了。下方的评论(stackoverflow.com/a/21203783/285154)是最佳选择。
dimitarvp 2014年

谢谢!在Rails 4.2中,这仍然是一个问题,也许仅当您在多个级别中使用继承控制器时。我以前使用过方法,但是当我遇到问题时,我并没有考虑进行测试,再次感谢。
244

@dimitko不,不是,我已经在问题本身中引用了该解决方案。如果要使用3个或更多不同的布局(这正是我的情况),它将不起作用。
mrbrdo '16

201

如果仅在两种布局之间进行选择,则可以使用:only

class ProductsController < ApplicationController
   layout "admin", only: [:new, :edit]
end

要么

class ProductsController < ApplicationController
   layout "application", only: [:index]
end

2
好吧,这样做的问题是您无法访问诸如current_user之类的对象来有条件地确定布局
Andrew K

@AndrewK动态选择布局似乎并不是所问问题的一部分。
尼克

11
如果您中的任何一个人阅读了该问题,您将知道这不是正确的答案,因为我已经在问题本身中描述了此解决方案,以及为什么它在我的情况下不起作用(3种或更多布局)。
mrbrdo

2
就像mrbrdo所说,这不是答案。他的问题具体表明(I am using 3 or more different layouts in the same controller)。这个答案允许一个布局,没有布局,没有不同的布局。
迈克尔

49

您可以使用response_to指定单个动作的布局:

  def foo
    @model = Bar.first
    respond_to do |format|
      format.html {render :layout => 'application'}
    end
  end

对我来说,这是更灵活的答案。通过应用layout "[...]" to the controller class only allows one statement effectively. If you have more than two layouts to deal with (say, admin, generic_app, tailored_app), you will experience Render和/或重定向使事情变干在此操作错误中多次被调用;而且您别无选择,只能使用这个建议。
杰罗姆

1
与使用内部带有switch或if语句的方法相反,此答案是最好的,它简单明了。
kev

还可以指定该局文件和布局都:format.html { render 'custom_index', layout: 'application' } 以同样的方式。
thatway_3,2014年

12

您还可以使用render指定操作的布局:

def foo
  render layout: "application"
end


7

在控制器下指定布局的各种方法:

  1. 在以下代码中,在索引下调用application_1布局,并显示Users控制器的show动作,并为其他动作调用application布局(默认布局)。

    class UsersController < ApplicationController
      layout "application_1", only: [:index, :show]
    end
  2. 在以下代码中,将对User控制器的所有操作调用application_1布局。

    class UsersController < ApplicationController
       layout "application_1"
    end
  3. 在以下代码中,仅对用户控制器的测试操作调用application_1布局,对于所有其他操作,将调用应用程序布局(默认)。

        class UsersController < ApplicationController
          def test
            render layout: "application_1"
          end
        end

5

精度:

上面看到的是一种不是真正但有效的DRY方式,但是具有一定的精度:布局必须位于变量之后才能使用(“ @some”)。作为:

def your_action
   @some = foo
   render layout: "your_layout"
end

并不是 :

def your_action
   render layout: "your_layout"
   @some = foo
   @foo = some
end

如果您执行before_action ...也将无法正常工作。

希望能帮助到你。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.