Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a variable to a layout?

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
like image 378
Andrew Avatar asked Sep 12 '11 01:09

Andrew


4 Answers

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.

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

like image 62
DanneManne Avatar answered Nov 10 '22 13:11

DanneManne


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
like image 13
Andrew Avatar answered Nov 10 '22 14:11

Andrew


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

#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.

#2

You could just use the local_assigns variable like:

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

and then in any of your controller:

render :locals => { :flag => true }
like image 9
p1100i Avatar answered Nov 10 '22 14:11

p1100i


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

like image 8
Dave Newton Avatar answered Nov 10 '22 14:11

Dave Newton