Matthew Denner
2005-Sep-28 16:32 UTC
Wondering how people would tend to do helpers for complex HTML structures
Hi, I''m working on a scrolling component for a project and I''d like some advice on writing a helper for this. Essentially the structure is a list inside another list: <ul> <li><a href="#">«</a></li> <li><a href="#">»</a></li> <li class="content"> <ul id="scrollable"> <li>image 1</li> <li>image 2</li> <li>image 3</li> <li>image 4</li> </ul> </li> </ul> These two lists display inline, and the ''content'' element is such that you only see a few of the images. So you see something like: << image 1 image 2 image 3 >> Clicking the >> moves the stuff across so you see: << image 2 image 3 image 4 >> Now, I''ve got all of the Javascript and the CSS to do this appropriately and I wrote a really dodgy Rails helper to do this, but what I really want to know is how people would write this helper properly. My thoughts are to do something with the ''capture'' method: def scrollable(id, &content_block) capture do ''<ul><li><a href="#">«</a></li><li><a href="#">»</li>'' + ''<li class="content">'' + content_block.call + ''</li>'' + ''</ul>'' end end For instance. Then my webbie people could do: <%= scrollable(''scroll_me'') do -%> <ul id="scroll_me"> <li>image 1</li> <li>image 2</li> <li>image 3</li> <li>image 4</li> </ul> <% end -%> Or put whatever content they see fit in there. But I have two problems with this: 1. Calling ''capture'' in that method errors with "undefined local variable or method `_erbout'' for #<ActionView::Base:0x3095fce0>". Little lost as to why that might be as ''content_for'' appears to do similar, and I''d love for someone to tell me what I''ve done wrong. 2. I''d really like the component to be as reuseable as possible, so I''d like the « and » to be changeable by the developer. For instance, they might want to use images of arrows instead. So my thought, for 2, was to use partials, and call out to them. Something like: def scrollable(id, &content_block) capture do ''<ul>'' + ''<li><a href="#">'' + render(:partial => ''scrollable/left'') + ''</a></li>'' + ''<li><a href="#">'' + render(:partial => ''scrollable/right'') + ''</li>'' + ''<li class="content">'' + content_block.call + ''</li>'' + ''</ul>'' end end Then someone with HTML skills could change the partial without knowing about the code in ''scrollable''. How would you more knowledgeable people do it? Would you write the HTML inside the method, use the partials as I have, just make the whole method call out to a partial, or something completely different? Matt p.s. I didn''t actually check the code in this email so please don''t point-and-snigger ;)
Trevor Squires
2005-Sep-28 20:08 UTC
Re: Wondering how people would tend to do helpers for complex HTML structures
Hi Matthew, it''s been a real learning experience looking at this message, comments inline: On 28-Sep-05, at 9:32 AM, Matthew Denner wrote:> def scrollable(id, &content_block) > capture do > ''<ul><li><a href="#">«</a></li><li><a href="#">»</li>'' > + > ''<li class="content">'' + content_block.call + ''</li>'' + > ''</ul>'' > end > end >-- Snipped --> But I have two problems with this: > > 1. Calling ''capture'' in that method errors with "undefined local > variable or method `_erbout'' for #<ActionView::Base:0x3095fce0>". > Little lost as to why that might be as ''content_for'' appears to do > similar, and I''d love for someone to tell me what I''ve done wrong. >actually it''s *not* doing something similar at all. Think about what local variables or methods exist when the block is *defined*. ''capture'' and ''content_for'' both *accept* blocks someone else defined (in an erb template). Your scrollable method *creates* a block to pass to ''capture'' so there is no _erbout variable. how about this for a cruel and unusual hack: def scrollable(id, &content_block) _erbout = eval("_erbout", block.binding) capture do ..... I haven''t tried it but it seems like it ought to do the trick... HTH, Trevor
Matthew Denner
2005-Sep-28 21:49 UTC
Re: Wondering how people would tend to do helpers for complex HTML structures
On 9/28/05, Trevor Squires <trevor-k8q5a0yEZAgS+FvcfC7Uqw@public.gmane.org> wrote:> it''s been a real learning experience looking at this message, comments > inline:I too have been on a bit of a learning journey after your email came in. I never knew about the Binding class (never had cause to until now I guess), nor had I had any call to use ''eval("x", binding)''. I feel I have so much more to learn!> how about this for a cruel and unusual hack: > > def scrollable(id, &content_block) > _erbout = eval("_erbout", block.binding) > capture do > ..... > > I haven''t tried it but it seems like it ought to do the trick...Thanks, it did, but then I changed my idea slightly because your comments made me think. I ended up with: def scrollable(id, &content_block) render :partial => ''common/scrollable'', :locals => { :id => id, :content => capture(&content_block) } end My partial then has: <ul> <li><a href="#">«</li> <li><a href="#">»</li> <li class="content"><%= content -%></li> </ul> And then in my view: <% x = scrollable(''scroll_me'') do -%> <ul id="scroll_me"> ... li''s of images </ul> <% end -%> <%= x -%> I don''t like the assignment of a vairable and then displaying it, but if I use a "<%= scrollable(''scoll_me'') do -%>" the ERB code seems to want to turn that one line into a string, rather than all the way to the end of the block. Perfectly reasonable for ERB to do that, it just makes it look slightly uglier. I can now reuse this and have the webbie people do their thing on the partial. Matt