如何将变量传递给布局?

时间:2022-01-06 20:42:29

I have a two versions of my application layout, which are differs only in a few lines. Consider following example:

我的应用程序布局有两个版本,它们只在几行中有所不同。考虑下面的例子:

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

The question is, how do I pass this flag to the layout?

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

class ApplicationController < ActionController::Base
    layout 'layout', :locals => {:flag => true} #won't work :(

    # ...
end

5 个解决方案

#1


8  

A controller instance variable? That's the normal way to get information to the template.

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

#2


15  

I usually prefer to use helper methods instead of instance variables in these situations. Here is an example of how it could be done:

在这些情况下,我通常更喜欢使用辅助方法而不是实例变量。下面是一个如何做到这一点的例子:

class ApplicationController < ActionController::Base
  layout 'layout'
  helper_method :flag

  ...

protected
  def flag
    true
  end
end

And if you have a controller where flag should not be true then you just overwrite the method:

如果你有一个控制器,标志不为真那么你就重写方法:

class PostsController < ApplicationController
  ...

private
  def flag
    false # or perhaps do some conditional
  end
end

This way you make sure that the flag helper is always available in views so you don't have to do the if defined? or anything and also, in the cases where no layout is used, then no instance variable is assigned in any before_filter.

这样,您就可以确保在视图中始终可以使用标志助手,这样您就不必执行if定义了吗?或者任何东西,而且,在不使用布局的情况下,在任何before_filter中都不会分配实例变量。

It also helps keep as few instance variables as possible in the views.

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

#3


12  

Okay, so I found the solution by myself:

我自己找到了解决办法

class ApplicationController < ActionController::Base
    layout 'layout'
    before_filter :set_constants

    def set_constants
        @flag = true
    end
end

And the template should be:

模板应该是:

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

#4


8  

There is two another option to do, what actually the OP asked:

还有另外两个选择,OP的要求是:

#1

in your layout:

在你的布局:

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

in your application controller (this is the trick):

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

layout 'application' # or whatever

in any kind of controller:

在任何类型的控制器中:

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

My guess would be, the layout processing is happening later cause of the "dynamic" (not really) layout definition and that generates the necessary methods for all the keys inside of local_assigns. So maybe the instance variable is a performanter solution. Any thoughts about that? Please leave a comment.

我的猜测是,由于“动态”(不是真正的)布局定义,布局处理将在稍后进行,并为local_assign中的所有键生成必要的方法。也许实例变量是一个性能更好的解决方案。有什么想法吗?请留下你的评论。

#2

You could just use the local_assigns variable like:

可以使用local_赋值变量,比如:

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

and then in any of your controller:

然后在任何一个控制器中

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

#5


-1  

What about this http://snippets.dzone.com/posts/show/236 in order to conditionally select layouts?

这个http://snippets.dzone.com/posts/show/236可以有条件地选择布局吗?

#1


8  

A controller instance variable? That's the normal way to get information to the template.

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

#2


15  

I usually prefer to use helper methods instead of instance variables in these situations. Here is an example of how it could be done:

在这些情况下,我通常更喜欢使用辅助方法而不是实例变量。下面是一个如何做到这一点的例子:

class ApplicationController < ActionController::Base
  layout 'layout'
  helper_method :flag

  ...

protected
  def flag
    true
  end
end

And if you have a controller where flag should not be true then you just overwrite the method:

如果你有一个控制器,标志不为真那么你就重写方法:

class PostsController < ApplicationController
  ...

private
  def flag
    false # or perhaps do some conditional
  end
end

This way you make sure that the flag helper is always available in views so you don't have to do the if defined? or anything and also, in the cases where no layout is used, then no instance variable is assigned in any before_filter.

这样,您就可以确保在视图中始终可以使用标志助手,这样您就不必执行if定义了吗?或者任何东西,而且,在不使用布局的情况下,在任何before_filter中都不会分配实例变量。

It also helps keep as few instance variables as possible in the views.

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

#3


12  

Okay, so I found the solution by myself:

我自己找到了解决办法

class ApplicationController < ActionController::Base
    layout 'layout'
    before_filter :set_constants

    def set_constants
        @flag = true
    end
end

And the template should be:

模板应该是:

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

#4


8  

There is two another option to do, what actually the OP asked:

还有另外两个选择,OP的要求是:

#1

in your layout:

在你的布局:

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

in your application controller (this is the trick):

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

layout 'application' # or whatever

in any kind of controller:

在任何类型的控制器中:

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

My guess would be, the layout processing is happening later cause of the "dynamic" (not really) layout definition and that generates the necessary methods for all the keys inside of local_assigns. So maybe the instance variable is a performanter solution. Any thoughts about that? Please leave a comment.

我的猜测是,由于“动态”(不是真正的)布局定义,布局处理将在稍后进行,并为local_assign中的所有键生成必要的方法。也许实例变量是一个性能更好的解决方案。有什么想法吗?请留下你的评论。

#2

You could just use the local_assigns variable like:

可以使用local_赋值变量,比如:

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

and then in any of your controller:

然后在任何一个控制器中

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

#5


-1  

What about this http://snippets.dzone.com/posts/show/236 in order to conditionally select layouts?

这个http://snippets.dzone.com/posts/show/236可以有条件地选择布局吗?