584559348afbc5cc06c46c3b5746313a

This is from the documentation for ERB. Can someone explain how the template blocks work in this example in the build method. I feel like I'm missing something. It seems like that's invalid syntax.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
require "erb"

# build data class
class Listings
  PRODUCT = { :name => "Chicken Fried Steak",
              :desc => "A well messages pattie, breaded and fried.",
              :cost => 9.95 }

  attr_reader :product, :price

  def initialize( product = "", price = "" )
    @product = product
    @price = price
  end

  def build
    b = binding
    # create and run templates, filling member data variebles
    ERB.new(<<-'END_PRODUCT'.gsub(/^\s+/, ""), 0, "", "@product").result b
      <%= PRODUCT[:name] %>
      <%= PRODUCT[:desc] %>
    END_PRODUCT
    ERB.new(<<-'END_PRICE'.gsub(/^\s+/, ""), 0, "", "@price").result b
      <%= PRODUCT[:name] %> -- <%= PRODUCT[:cost] %>
      <%= PRODUCT[:desc] %>
    END_PRICE
  end
end

# setup template data
listings = Listings.new
listings.build

puts listings.product + "\n" + listings.price

Refactorings

No refactoring yet !

Bfec5f7d1a4aaafc5a2451be8c42d26a

macournoyer

October 25, 2007, October 25, 2007 02:31, permalink

No rating. Login to rate!

ERB.new last parameter specify in which variabe the tempate will be rendered in. This is required when rendering more then one template w/ the same bindings.
I don't know which part you don't understand, here's some code, spliting it up a bit more:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
require 'erb'

text = <<-EOS
  Some text with:
    <%= @vars %>
EOS

puts text 
#    Some text with:
#      <%= @vars %>

puts text.gsub(/^\s+/, "")
# Some text with:
# <%= @vars %>

@vars = 'my value'

puts ERB.new(text).result(binding)
#    Some text with:
#      my value    
 
E635ccff7389d9070f5e7e9fe8b36beb

rpheath

October 25, 2007, October 25, 2007 02:36, permalink

No rating. Login to rate!

So if I wanted to build an application that allowed stuff like <%= Time.now %> in some textarea, all I'd have to do for that to work is something like this???

1
@text = ERB.new(params[:textarea_body]).result(binding)
Bfec5f7d1a4aaafc5a2451be8c42d26a

macournoyer

October 25, 2007, October 25, 2007 15:43, permalink

No rating. Login to rate!

That might be a security hole, as the params[:textarea_body] will be evaled. Still it will be evaled in tainted mode but a user could sure alter any of the variables in the current binding he wants, small example here of what could be possible.

Not to says that the @controller instance is also accessible

1
<% @@content_for_layout = "<script>alert('I can do whatever I want here!')</script>" %>
584559348afbc5cc06c46c3b5746313a

daveg

October 25, 2007, October 25, 2007 18:11, permalink

No rating. Login to rate!

The part I didn't understand was the use of a HERE-DOC that starts on the following line being modified before it's declared. the gsub method is being called on the string that's defined on the lines below.

As for the security hole, this code is copied out of the documentation for ERB. It's only an example.

4d1c9dad17af98e55cb65b4efce27c42

Ben Burkert

October 26, 2007, October 26, 2007 06:07, permalink

1 rating. Login to rate!

That's actually a little syntactical sugar in Ruby. Basically, when the interpreter sees the heredoc, it jumps to the next line and starts building the string until it reaches the identifier. Then it continues on the first line, after the heredoc. You can even start multiple heredoc's on the same line.

1
2
3
4
5
6
<<-HELLO + <<-WORLD
hello,
HELLO
world!
WORLD
# => "hello,\nworld!\n"

Your refactoring





Format Copy from initial code

or Cancel