From: Rob Biedenharn Date: 2009-02-02T06:04:55+09:00 Subject: Re: Could someone please explain the magic in this code On Feb 1, 2009, at 3:15 PM, John Small wrote: > I need to use erb templates so I went to look at the documentation. It > all seems straight forwards until I get to the example where a lot of > new coding concepts are pulled in and I'm left totally mystified about > what's going on. > > The code, from the api documentation is >
> 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
>
> 
> My questions are;- > > (1) what does "<<-" do just before 'END_PRODUCT' That's a "here document". <<-'END_PRODUCT' means to take the following lines up until a line begins with END_PRODUCT as if they were a string. The - let's END_PRODUCT be indented from the beginning of the line. The single quotes say that no interpolation is to be done on the string (that is, it should act like a string literal with single quotes). > > (2) how do the lines after .result b get substituted into END_PRODUCT I hope (1) answers that ... > > and why is there a gsub there. The gsub is removing the leading whitespace /^\s+/ from each line. This lets the here-document contents be intended to where code would normally be. > My understanding of the order things are > happening is clearly deficient because the gsub to remove white space > will have no effect on 'END_PRODUCT' since there's no white space in > it. > So somehow 'END_PRODUCT' is getting replaced by the lines below, which > aren't in quotes, before the gsub happens. wtf is going on here? Do you get it now? The equivalent would look like: ERB.new("<%= PRODUCT[:name] %>\n<%= PRODUCT[:desc] %>\n", 0, "", "@product").result b If the here-document were not used. > > (3) How does binding work? The documentation is pretty opaque. What is > it doing in this context and why is it required? You want the PRODUCT, @product, and @price to be evaluated in the context of the Listings object rather than the new ERB object just created. > > > All explanations welcome > -- > Posted via http://www.ruby-forum.com/. > I hope this helps. -Rob Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com