如何将变量传递给布局?

时间:2011-09-12 01:19:33

标签: ruby-on-rails ruby layout

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

!!!    
%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 < ActionController::Base
    layout 'layout', :locals => {:flag => true} #won't work :(

    # ...
end

5 个答案:

答案 0 :(得分:16)

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

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中分配。

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

答案 1 :(得分:13)

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

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

答案 2 :(得分:8)

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

答案 3 :(得分:8)

还有另外两个选项,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 }

答案 4 :(得分:-1)

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