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 !
macournoyer
October 25, 2007, October 25, 2007 02:31, permalink
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
rpheath
October 25, 2007, October 25, 2007 02:36, permalink
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)
macournoyer
October 25, 2007, October 25, 2007 15:43, permalink
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>" %>
daveg
October 25, 2007, October 25, 2007 18:11, permalink
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.
Ben Burkert
October 26, 2007, October 26, 2007 06:07, permalink
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"
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.