Class: Renderer

Inherits:
Object
  • Object
show all
Defined in:
lib/renderer.rb

Overview

The Renderer is the heart-piece of each Generator::Generator, but can also be used without them. It uses ERB-Templates, which are being rendered with a binding to the Renderer-instance.

It’s only method #render can be used in multiple ways, which are explained here. The Renderer is automatically been set up by the Generator, but to understand how it works we may setup it ourselves like:

my_renderer = Renderer.new 'my/template/path', 'layout/application'
my_renderer.render 'test', :to_file => 'output.html'

This will render the template ‘my/template/path/test.html.erb` in the layout `my/template/path/layout/application.html.erb` and saved to `output.html`.

Most of the time, as with Generators, the renderer will be extended and used like:

class MyRenderer < Renderer

   def initialize
     super('my/template/path', 'layout/application')
   end

   def index
     render 'test', :to_file => 'output.html'
   end
 end

Direct Known Subclasses

Generator::Generator

Instance Method Summary collapse

Constructor Details

#initialize(default_path, layout) ⇒ Renderer

Returns a new instance of Renderer.



31
32
33
34
# File 'lib/renderer.rb', line 31

def initialize(default_path, layout)
  @_path = default_path
  @_layout = layout
end

Instance Method Details

#render(template, *opts) ⇒ String? #render(: partial=>template, : collection=>[...]) ⇒ String #render(: partial=>template, : locals=>{...}) ⇒ String

Note:

Pretty much inspired by Ruby on Rails

Examples:

simple rendering

render 'test', :layout => nil #=> returns a string, containing the rendered template 'test.html.erb'

rendering within a layout

# layout/app.html.erb
<html>
   <%= yield %>
</html>

# MyCustomRenderer < Renderer
render 'test', :layout => 'layout/app' #=> renders 'test.html.erb' within 'app.html.erb'

rendering a partial with collections

# _item.html.erb
<li><%= item %></li>   

# my_view.html.erb
<ul>
  <%= render :partial => 'item', :collection => ["Foo", "Bar", "Baz"]
</ul>

#=> <ul><li>Foo</li><li>Bar</li><li>Baz</li></ul>

setting local-variables within a partial

# _item.html.erb
<strong><%= foo %></strong> <em><%= bar %></em>

# my_view.html.erb
<%= render :partial => 'item', :locals => { :foo => "Hello", :bar => "World" } %>

#=> <strong>Hello</strong> <em>World</em>

rendering to file

render 'my_test', :to_file => "test_output.html"

Overloads:

  • #render(template, *opts) ⇒ String?

    Options opts:

    • :layout (String) Default is specified in constructor. For example ‘’json’‘ or `’application’‘

    • :to_file (String) Optional file-path to save the output to.

    Parameters:

    • template (String, Symbol)

      Template-file without file-extension. (Like ‘index` => `index.html.erb`)

    • opts (Hash)

    Returns:

    • (String, nil)

      the rendered output

  • #render(: partial=>template, : collection=>[...]) ⇒ String

    For each item of ‘collection`, the partial will be rendered once. The output consists of all those concatenated render-passes. The value of each item will be bound to a local-variable called like the partial, without leading _. (i.e. if partial-name = “_test.html.erb” the variable is called `test`

    Options opts:

    • :template (String, Symbol) Template-file without file-extension. (Like ‘index` => `index.html.erb`)

    • :collection (Array)

    Parameters:

    • opts (Hash)

    Returns:

    • (String)

      the rendered output

  • #render(: partial=>template, : locals=>{...}) ⇒ String

    Each key of ‘locals` will be set to it’s value in the local-binding of the partial.

    Options opts:

    • :template (String, Symbol) Template-file without file-extension. (Like ‘index` => `index.html.erb`)

    • :locals (Hash) Hash of variables, which will be available via local-variables in the partial-binding

    Parameters:

    • opts (Hash)

    Returns:

    • (String)

      the rendered output

See Also:



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/renderer.rb', line 111

def render(opt = nil, extra_options = {})

  # Prepare Options
  if opt.nil?
    opt = { :layout => @_layout }

  elsif opt.is_a?(String) || opt.is_a?(Symbol)
    extra_options[:template] = opt
    extra_options[:layout] ||= @_layout
    opt = extra_options

  elsif !opt.is_a?(Hash)
    extra_options[:partial] = opt
    opt = extra_options
  end

  if opt[:partial]
    render_partial opt
    
  else    
    # bind @current_path correctly to use in helpers and views
    if opt[:to_file]
      # Make absolute
      opt[:to_file] = File.expand_path(opt[:to_file], Configs.output)        
      @current_path = File.dirname opt[:to_file]
    else
      @current_path ||= Configs.output
    end

    # render 'view_name', :option1 => 1, :option2 => 2
    template = path_to_template opt[:template]
    begin
      view = ERB.new(File.read template).result(binding)
    rescue Exception => e
      raise "Error while rendering #{template}\n#{e.message}"
    end

    
    # then render with layout
    if opt[:layout]
      layout = File.read path_to_template opt[:layout]
      view = render_in_layout(layout) { view }
    end

    # Render to file, if desired
    if opt[:to_file]
      # create directories recursive
      FileUtils.mkpath File.dirname opt[:to_file]

      # Working with Thor-Actions would be nice, but it seems to be too much overhead for this small
      # renderer
      File.open(opt[:to_file], "w+") do |f|
        f.write view
      end
    else        
      return view
    end
  end
 
end