如何将变量传递给布局?

我有两个版本的应用程序布局,它们只有几行不同。 请考虑以下示例:

!!! %html %head # a lot of code here %body # some more code here - if defined? flag and flag == true # variant 1 - else # variant 2 

问题是,如何将此标志传递给布局?

 class ApplicationController  {:flag => true} #won't work :( # ... end 

控制器实例变量? 这是获取模板信息的常用方法。

在这些情况下,我通常更喜欢使用辅助方法而不是实例变量。 以下是如何完成的示例:

 class ApplicationController < ActionController::Base layout 'layout' helper_method :flag ... protected def flag true end end 

如果你有一个控制器,其中flag不应该是true,那么你只需覆盖该方法:

 class PostsController < ApplicationController ... private def flag false # or perhaps do some conditional end end 

这样,您可以确保标记帮助程序始终在视图中可用,因此您不必执行if defined? 或者任何东西,并且在没有使用布局的情况下,在任何before_filter中都没有分配实例变量。

它还有助于在视图中保留尽可能少的实例变量。

好的,所以我自己找到了解决方案:

 class ApplicationController < ActionController::Base layout 'layout' before_filter :set_constants def set_constants @flag = true end end 

模板应该是:

 !!! %html %head # a lot of code here %body # some more code here - if @flag # variant 1 - else # variant 2 

另外还有两个选择 ,OP实际上是这样做的:

#1

在你的布局中:

 - if flag ||= false # variant 1 - else # variant 2 

在您的应用程序控制器中(这是技巧):

 layout 'application' # or whatever 

在任何类型的控制器:

 render :locals => { :flag => true } 

我的猜测是,布局处理后来发生了“动态”(不是真正的) layout定义,并为local_assigns内的所有键生成必要的方法。 因此,实例变量可能是一种性能解决方案。 有什么想法吗? 请发表评论。

#2

您可以使用local_assigns变量,如:

 - if local_assigns[:flag] ||= false # variant 1 - else # variant 2 

然后在你的任何一个控制器中:

 render :locals => { :flag => true } 

为了有条件地选择布局,这个http://snippets.dzone.com/posts/show/236怎么样?