I have seen a number of examples where HTML code is treated as a Ruby block. For example, here is one taken from the Agile Rails book: <% content_for( :sidebar) do %> <ul> <li>this text will be rendered</li> <li>and saved for later</li> <li>it may contain <%= "dynamic" %> stuff</li> </ul> <% end %> I have no idea how this works. Can someone please give me a clue as to how this works? Additionally (and this is what I am really trying to do) I''m wondering if there isn''t some way I could use this approach to display a block of HTML code conditionally. Any ideas? Thanks for any input. ... doug
> I have seen a number of examples where HTML code is treated as a Ruby > block. For example, here is one taken from the Agile Rails book: > > <% content_for( :sidebar) do %> > <ul> > <li>this text will be rendered</li> > <li>and saved for later</li> > <li>it may contain <%= "dynamic" %> stuff</li> > </ul> > <% end %> > > I have no idea how this works. Can someone please give me a clue as > to how this works? Additionally (and this is what I am really trying > to do) I''m wondering if there isn''t some way I could use this approach > to display a block of HTML code conditionally. Any ideas?Not sure what you mean by conditionally... if it''s something server side you could just do: <% if this_expression_evaluates_to_true %> put your html here <% end %> The way content_for works is to capture the result of the block (everything in b/n) and save it for later. You can get it back by doing <%= yield :sidebar %> -philip
On Jun 18, 8:27 pm, doug <ddjol...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I have seen a number of examples where HTML code is treated as a Ruby > block. For example, here is one taken from the Agile Rails book: > > <% content_for( :sidebar) do %> > <ul> > <li>this text will be rendered</li> > <li>and saved for later</li> > <li>it may contain <%= "dynamic" %> stuff</li> > </ul> > <% end %> > > I have no idea how this works. Can someone please give me a clue as > to how this works? Additionally (and this is what I am really trying > to do) I''m wondering if there isn''t some way I could use this approach > to display a block of HTML code conditionally. Any ideas? >It captures the block and stashes it away for later. Don''t you just want <% if something %> html here <% end %> though ? Fred> Thanks for any input. > > ... doug
2009/6/18 doug <ddjolley-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:> > I have seen a number of examples where HTML code is treated as a Ruby > block. For example, here is one taken from the Agile Rails book: > > <% content_for( :sidebar) do %> > <ul> > <li>this text will be rendered</li> > <li>and saved for later</li> > <li>it may contain <%= "dynamic" %> stuff</li> > </ul> > <% end %> > > I have no idea how this works. Can someone please give me a clue as > to how this works? Additionally (and this is what I am really trying > to do) I''m wondering if there isn''t some way I could use this approach > to display a block of HTML code conditionally. Any ideas? > > Thanks for any input. > > ... dougIt might be worth your while working through some of the rails guides at http://guides.rubyonrails.org/, particularly the Getting Started guide. This should get you going with the fundamental operation of Rails. Good luck Colin
> Not sure what you mean by conditionally... if it''s something server > side you could just do: > > <% if this_expression_evaluates_to_true %> > put your html here > <% end %>That is exactly what I''m talking about and it gives me a great basis for trying to articulate what is confusing me. I am apparently under the mistaken impression that when we insert into an HTML document Ruby code that is included within <% %> like this: <% ruby code %> the inserted Ruby code is run at the point where it is inserted into the HTML document. When that Ruby code completes, any HTML code that follows is sent to the requesting browser. The point is that at any given time either Ruby code is being run or HTML is being sent to the requesting browser. What your Ruby code does is interact with a segment of HTML code so that that segment of HTML code is sent to the browser conditionally. That just blows my mind. How are we able to accomplish that? Or, is that just something that I should accept and try not to think about too much? I would think that if we were going to include content conditionally, that content would have to be within the <% %> and quoted. My concern is that I am missing some very important point about <% %> that, if I weren''t missing it, my understanding would be a whole lot better.> The way content_for works is to capture the result of the block > (everything in b/n) and save it for later.Yes. I understand what content_for does. I was just using it to provide an example of the type of thing that I was talking about. Thanks to all for the input. ... doug
On Jun 18, 2009, at 10:03 PM, djolley wrote:> >> Not sure what you mean by conditionally... if it''s something server >> side you could just do: >> >> <% if this_expression_evaluates_to_true %> >> put your html here >> <% end %> > > That is exactly what I''m talking about and it gives me a great basis > for trying to articulate what is confusing me. > > I am apparently under the mistaken impression that when we insert into > an HTML document Ruby code that is included within <% %> like this: > > <% ruby code %> > > the inserted Ruby code is run at the point where it is inserted into > the HTML document. When that Ruby code completes, any HTML code that > follows is sent to the requesting browser. The point is that at any > given time either Ruby code is being run or HTML is being sent to the > requesting browser. What your Ruby code does is interact with a > segment of HTML code so that that segment of HTML code is sent to the > browser conditionally. That just blows my mind. How are we able to > accomplish that? Or, is that just something that I should accept and > try not to think about too much?Being inquisitive about the code you are running is a good thing. If you really want to know, every Ruby installation ships with erb.rb in the /path/to/lib/ruby/1.x/ directory. But the shorter path to your answer is that ERB scans your code for lines with <% and %> in them. The code inside is evaluated using the eval method. If there is an equal sign (<%=), then the results of the expression evaluation are concatenated to the end of the output stream. Anything outside the <% delimiters is treated as a string to be concatenated directly to the end of the output stream. This is an oversimplification, but that should give you an idea what makes things tick. The key concept is that no output is generated and no expressions evaluated until the moment a page is rendered. The Ruby doesn''t so much interact with the HTML code as to accept the HTML code as arbitrary strings that are (according to normal Ruby control flow statements) concatenated onto an output stream.> I would think that if we were going > to include content conditionally, that content would have to be within > the <% %> and quoted. My concern is that I am missing some very > important point about <% %> that, if I weren''t missing it, my > understanding would be a whole lot better. > >> The way content_for works is to capture the result of the block >> (everything in b/n) and save it for later. > > Yes. I understand what content_for does. I was just using it to > provide an example of the type of thing that I was talking about. > > Thanks to all for the input. > > ... doug > >
Thanks so much for your kind explanation. Unfortunately, it still doesn''t make sense to me. The documentation for the ERB class tells us: <% Ruby code -- inline with output %> <%= Ruby expression -- replace with result %> That makes perfect sense. The documentation even alludes to the capability in question in an example; but, it really isn''t discussed. In discussing <% %>, the Agile Rails book makes the observation, "Interestingly, this kind of processing can be intermixed with non- ruby code." Then they give a minor example and launch into a discussion dealing with extraneous new line characters. Am I alone in thinking that this is a monumental capability that deserves a better understanding? Anyway, thanks very much for the response. I''m sorry that it didn''t quite bridge the gap for me. I guess that I either have a mental block or am just super dense. Thanks again. ... doug
2009/6/19 djolley <ddjolley-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:> > Thanks so much for your kind explanation. Unfortunately, it still > doesn''t make sense to me. > > The documentation for the ERB class tells us: > > <% Ruby code -- inline with output %> > <%= Ruby expression -- replace with result %> > > That makes perfect sense. The documentation even alludes to the > capability in question in an example; but, it really isn''t discussed. > In discussing <% %>, the Agile Rails book makes the observation, > "Interestingly, this kind of processing can be intermixed with non- > ruby code." Then they give a minor example and launch into a > discussion dealing with extraneous new line characters. > > Am I alone in thinking that this is a monumental capability that > deserves a better understanding? > > Anyway, thanks very much for the response. I''m sorry that it didn''t > quite bridge the gap for me. I guess that I either have a mental > block or am just super dense. Thanks again. >Have you tried working through the Getting Started guide at http://guides.rubyonrails.org/ ? If not then doing that may help to clarify things. Colin
On Jun 19, 2009, at 11:51 AM, djolley wrote:> > Thanks so much for your kind explanation. Unfortunately, it still > doesn''t make sense to me. > > The documentation for the ERB class tells us: > > <% Ruby code -- inline with output %> > <%= Ruby expression -- replace with result %> > > That makes perfect sense. The documentation even alludes to the > capability in question in an example; but, it really isn''t discussed. > In discussing <% %>, the Agile Rails book makes the observation, > "Interestingly, this kind of processing can be intermixed with non- > ruby code." Then they give a minor example and launch into a > discussion dealing with extraneous new line characters. > > Am I alone in thinking that this is a monumental capability that > deserves a better understanding? > > Anyway, thanks very much for the response. I''m sorry that it didn''t > quite bridge the gap for me. I guess that I either have a mental > block or am just super dense. Thanks again. > > ... dougOk, I oversimplified it. This discussion really belongs on the ruby- talk ML, but here is the longer explanation. Assuming you have the code: require ''rubygems'' require ''erb'' template =<<EOD This is plain text And the time is <%= Time.now %> <% if true %> it was true <% else %> it wasn''t true <% end %> EOD puts ERB.new(template).result Then after compiling it, ERB creates: "_erbout = ''''; _erbout.concat \"This is plain text\\n \"\n_erbout.concat \"And the time is \"; _erbout.concat(( Time.now ).to_s); _erbout.concat \"\\n\"\n if true ; _erbout.concat \"\\n\"\n_erbout.concat \" it was true\\n\"\n else ; _erbout.concat \"\\n\"\n_erbout.concat \" it wasn''t true\\n\"\n end ; _erbout.concat \"\\n\"\n_erbout" Without getting into the details of how ERB scans and tokenizes the text, the point I want to make is that what you thought was HTML is nothing more than a bunch of strings to ERB. These strings are passed to eval, which evaluates and runs them as Ruby code. So check it out. I just reformatted the code above: "_erbout = '''' _erbout.concat \"This is plain text\\n\"\n_erbout.concat \"And the time is \" _erbout.concat(( Time.now ).to_s) _erbout.concat \"\\n\"\n if true _erbout.concat \"\\n\"\n_erbout.concat \" it was true\\n\"\n else _erbout.concat \"\\n\"\n_erbout.concat \" it wasn''t true\\n\"\n end _erbout.concat \"\\n\"\n_erbout" And you can see how the if and else affect what strings are output. For a more in-depth example, just do what I did: Create the ERB, punch it into rdebug, and step through it. Ain''t it cool to have source? Steve
> "_erbout = '''' > _erbout.concat \"This is plain text\\n\"\n_erbout.concat \"And the > time is \" > _erbout.concat(( Time.now ).to_s) > _erbout.concat \"\\n\"\n > if true > _erbout.concat \"\\n\"\n_erbout.concat \" it was true\\n\"\n > else > _erbout.concat \"\\n\"\n_erbout.concat \" it wasn''t true\\n\"\n > end > _erbout.concat \"\\n\"\n_erbout"Thanks so much, Steve. I think that I get the essence of how it works. It does not seem that erb directly translates an input document into an output stream. Rather, it appears that erb produces a Ruby program that, when run, produces the output stream. Lines of the input document that consist wholly of text (i.e., they do not contain any ''<%'' beginning markers or ''%>'' ending markers) are passed as an argument to a method called erbout.concat which adds the line to the output stream when the program is run. Thus, the intermediate program contains a series of calls to erbout.concat (one for each text line). Thus, if the input document contains no lines which include beginning or ending markers, the intermediate program consists exclusively of a series of calls to the erbout.concat method (one for each line of input) with the relevant line passed as an argument to the method. If such a program is run, it simply outputs the original document. Now, let''s see what happens when <% %> and <%= >%> markers are introduced into the document. First of all, any such content is treated as being placed on a separate line. So, if we we had: The quick brown <% fox %> jumped over the lazy dog. That would be treated as being: The quick brown <% fox %> jumped over the lazy dog The ''The quick brown'' and ''jumped over the lazy dog'' are now just plain lines of text and as such they are treated accordingly by each being passed as an argument to a call to the erbout.concat method. What do we do with <% fox %>? Pretty much nothing. We through away the beginning and ending markers and leave simply ''fox''. ''fox'' is now a fragment of Ruby code which will be run along with the other lines of code, e.g., calls to erbout.concat when the program is run. That only leaves us with figuring out how content within <%= and %> markers is treated. That''s pretty easy. The enclosed content is evaluated as a Ruby statement and the output is treated as a line of text which is passed as an argument to a separate call to erbout.concat. I think that''s basically it. I feel much better now. I welcome any comments on my analysis. Thanks to all who contributed. ... doug P.S. Colin, I didn''t mean to ignore you; but, I didn''t really see anything in the Getting Started Guide that would help me with this issue. Thanks for the input though. jumped over the lazy dog
steve that''s the first outline of erb I have seen. Either it doesn''t get discussed a lot, or it is discussed in places I don''t visit. Anyway, although I had a broad idea of what was going on under the bonnet, I had never really seen a clear example of an erb template in action. I use haml, and I have often wondered how it hooks into erb. With your example, I am inspired to delve into that a bit when I get some spare time. Thanks Tony
Tonypm wrote:> steve > > that''s the first outline of erb I have seen.Yes, thanks for that. I know intuitively how ERb works, but had never looked at the internals in any detail. [...]> I > use haml, and I have often wondered how it hooks into erb.As far as I know, it doesn''t (unless you use the :erb filter). It is a completely separate template handler, I think.> With your > example, I am inspired to delve into that a bit when I get some spare > time.Indeed!> > Thanks > TonyBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/.
On Jun 21, 2009, at 9:48 AM, Marnen Laibow-Koser <rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org > wrote:> > Tonypm wrote: >> steve >> >> that''s the first outline of erb I have seen.Glad to be of help.>> > > Yes, thanks for that. I know intuitively how ERb works, but had never > looked at the internals in any detail. > > [...] >> I >> use haml, and I have often wondered how it hooks into erb. > > As far as I know, it doesn''t (unless you use the :erb filter). It > is a > completely separate template handler, I think.Haml has a separate engine and the code is very readable. Go to your Gem directory or plugin directory and have a peek.> >> With your >> example, I am inspired to delve into that a bit when I get some spare >> time. > > Indeed! > >> >> Thanks >> Tony > > > Best, > -- > Marnen Laibow-Koser > http://www.marnen.org > marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org > -- > Posted via http://www.ruby-forum.com/. > > >
Doug, I recall I went through a similar ''wow'' experience, and it helped me sort out how this was working when I realised I could think of <% and %> in the reverse of the way they are normally presented. By that I mean, insted of seeing a <% %> pair as bracketing ruby code embedded in the middle of HTML, think of it as a %> <% pair bracketing text in the middle of ruby code. (This needs a bit of mind-twisting at first - not to mention odd details like an assumed %> at the beginning of the document.) Then imagine the resulting patterns such as %>html text<% as replaced by ruby code such as puts "html text" and it is easy to see why the text is output conditionally when it sits inside an ''if'' statement. (I am not suggesting that erb (or anything else) actually works this way, but I found it helped me see what was going on. YMMV ;-) ) Having read subsequent posts, I would comment that I have also discovered the joys of HAML and would not now use anything else. Graeme On Jun 20, 7:28 pm, djolley <ddjol...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > "_erbout = '''' > > _erbout.concat \"This is plain text\\n\"\n_erbout.concat \"And the > > time is \" > > _erbout.concat(( Time.now ).to_s) > > _erbout.concat \"\\n\"\n > > if true > > _erbout.concat \"\\n\"\n_erbout.concat \" it was true\\n\"\n > > else > > _erbout.concat \"\\n\"\n_erbout.concat \" it wasn''t true\\n\"\n > > end > > _erbout.concat \"\\n\"\n_erbout" > > Thanks so much, Steve. I think that I get the essence of how it > works. It does not seem that erb directly translates an input > document into an output stream. Rather, it appears that erb produces > a Ruby program that, when run, produces the output stream. Lines of > the input document that consist wholly of text (i.e., they do not > contain any ''<%'' beginning markers or ''%>'' ending markers) are passed > as an argument to a method called erbout.concat which adds the line to > the output stream when the program is run. Thus, the intermediate > program contains a series of calls to erbout.concat (one for each text > line). Thus, if the input document contains no lines which include > beginning or ending markers, the intermediate program consists > exclusively of a series of calls to the erbout.concat method (one for > each line of input) with the relevant line passed as an argument to > the method. If such a program is run, it simply outputs the original > document. > > Now, let''s see what happens when <% %> and <%= >%> markers are > introduced into the document. First of all, any such content is > treated as being placed on a separate line. So, if we we had: > > The quick brown <% fox %> jumped over the lazy dog. > > That would be treated as being: > > The quick brown > <% fox %> > jumped over the lazy dog > > The ''The quick brown'' and ''jumped over the lazy dog'' are now just > plain lines of text and as such they are treated accordingly by each > being passed as an argument to a call to the erbout.concat method. > What do we do with <% fox %>? Pretty much nothing. We through away > the beginning and ending markers and leave simply ''fox''. ''fox'' is now > a fragment of Ruby code which will be run along with the other lines > of code, e.g., calls to erbout.concat when the program is run. > > That only leaves us with figuring out how content within <%= and %> > markers is treated. That''s pretty easy. The enclosed content is > evaluated as a Ruby statement and the output is treated as a line of > text which is passed as an argument to a separate call to > erbout.concat. > > I think that''s basically it. I feel much better now. I welcome any > comments on my analysis. > > Thanks to all who contributed. > > ... doug > > P.S. Colin, I didn''t mean to ignore you; but, I didn''t really see > anything in the Getting Started Guide that would help me with this > issue. Thanks for the input though. > > jumped over the lazy dog