[erlyweb-list] Re: s and other non-component data</span></a></span> </h1> <p class="darkgray font13"> <span class="sender pipe"><a href="/search?l=erlyweb@googlegroups.com&q=from:%22David+King%22" rel="nofollow"><span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">David King</span></span></a></span> <span class="date"><a href="/search?l=erlyweb@googlegroups.com&q=date:20071118" rel="nofollow">Sun, 18 Nov 2007 00:42:40 -0800</a></span> </p> </div> <div itemprop="articleBody" class="msgBody"> <!--X-Body-of-Message--> <pre> >> {phased, {ewc, A}, >> fun(ExpandedEwc, MetaVals, Rendered) -> >> {ewc, html_container, [A, MetaVals, Rendered]} >> end}.</pre><pre> Yoi probably want to change the order of those arguments. If you have fun(ExpandedEwc, Rendered) then you should also have: fun(ExpandedEwc, Rendered, MetaVals) That is, keep the first few arguments consistent for the various forms, and when adding arguments, add them to the end, not the middle. >> This would simplify setting the Title, Header, etc from the >> controllers without using Bryan's clever ErlTL tricks (which may be >> less-than-intuitive for some people :) ), add too much magic to the >> framework, or even changing it much. It would also work trivially >> even >> when subcomponents are rendered in parallel because this is >> effectively a side-effect-free accumulator. > > That sounds good, and it avoids breaking backwards compatibility as > well. I do agree about changes to yaws_arg being a bad idea (although > it is currently possible for programs to change it before passing it > to children, that would be to be deliberate). > > The only problem I see is that if my controller function returns: > > [{add_property,{title,"The Title!"}}, > {data,"foo"}] > > Then what does my view function look like? These could both make > sense: > > <%@ fun([_,Data]) %> <!-- pass it through --> > > <%@ fun([Data]) %> <!-- pretend it didn't exist --> > > I wouldn't mind passing it through, but that does seem a bit strange > for children to be getting data intended for parents. Pretending it > didn't exist seems even stranger. > > > >> >>> >>> I really like the component system, so I'd definitely like to get >>> your feedback on my ideas since it's already going in a good >>> direction. >>> >>> I wouldn't expect the siblings to be guaranteed to receive it (since >>> clearly you can't guarantee that they all do, since some may have >>> already been evaluated, or may be being evaluated at the same time), >>> but I wouldn't expect them to be guaranteed to *not* receive it. >>> >>> Since the yaws_arg is being re-vamped anyway, maybe this should be >>> carried around on the yaws_arg. A simple plist is probably fine for >>> it. Then as the yaws_arg is returned changed it can be passed >>> through >>> changed. Then make all subcomponents pass the yaws_arg >>> implicitly: so >>> instead of {ewc,controller,func,[A,Foo]} calling func(A,Foo), make >>> {ewc,controller,func,[Foo]]} call fun(A,Foo). That way you're not >>> passing a stale yaws_arg accidentally. This is of course a >>> backwards- >>> breaking change, but not a difficult one to fix, since all of the >>> erlyweb code that I've seen and written passes it to the sub- >>> components anyway (even if it's not necessarily used). >>> >>> Otherwise, you end up all of the components doing something like >>> this: >>> >>> show(A,Foo) >>> NewA=yaws_arg:add_meta(A,[{title,get_the_title()}]), >>> >>> {return_with_meta,[{ewc,func,[NewA,Foo]}], >>> NewA}. >>> >>> (once again, with better names than return_with_meta and add_meta) >>> The worry here is that the subcomponents have to be called with NewA >>> instead of A, which seems ripe for forgetting to me (especially if >>> the yaws_arg some some validation before it passes it on; you could >>> pass invalid data to sub-components this way). >>> >>> I haven't looked at the contents of the yaws_arg, but if it's tagged >>> with a type, then you could just do this: >>> >>> show(A,Foo) >>> [_New_yaws_arg=yaws_arg:add_property(A,[{title,get_the_title >>> ()}]), >>> {ewc,func,[Foo]}]. >>> >>> Since erlyweb already knows to check the returned list for {ewc} and >>> whatnot, it could just check for a new yaws_arg and start using that >>> one. The problem there is that it forces {ewc}s to be processed >>> serially (since what do you do when you get two conflicting >>> yaws_args?), which my erlyweb does not (and given your blog post >>> on a >>> potential {concurrent,[{ewc,...}]}, I suspect this won't be a >>> guarantee forever). Another idea is to just add another return value >>> from controller functions: >>> >>> show(A,Foo) >>> [{add_property,{title,get_the_title()}}, >>> {add_property,{time_to_live,two_weeks()}} >>> {ewc,controller,func,[Foo]}, >>> {ewc,controller,fun2,[yaws_arg:get_property(cookies)]]. >>> >>> (this was has my implicit-passing of yaws_args, but it's not >>> necessary; not doing so does preclude children retrieving properties >>> from parents, but if they need that they should pass it as an >>> argument anyway). That doesn't carry the assumption that they are >>> processed serially. It prevents parents from getting to children's >>> properties without using {phased,Ewcs,...}, but that's probably >>> not a >>> problem, and isn't very avoidable. (I think all of these options do, >>> if they want to do post-processing of any kind). >>> >>> Personally, I like the last option, but it looks like it would >>> require quite a few changes to the way that the erlyweb:ewc/N >>> functions work >>> >>> Any other ideas? How does that last one look? >> >> >> >> >>> >>> >>> >>> >>>>>> Btw, just curious, what parts of ErlyWeb are you rewriting? >>>>> [...] >>>>> Mostly large swaths of erlydb and erlydb_mnesia (in ways that >>>>> make it >>>>> work better with mnesia, but that make it incompatible with other >>>>> DBMSs, which of course the current incarnation avoids). I may >>>>> end up >>>>> having to revert this if mnesia can't handle millions of objects, >>>>> with which it seems to be having trouble once they start to become >>>>> larger objects than simple tuples. I've hacked in a few return and >>>>> 'EXIT' handlers from controller functions for special >>>>> circumstances, >>>>> like when I want to return a 400- or 500-level HTTP response along >>>>> with other information. I might try to hack in some WebDAV >>>>> handling >>>>> stuff, as I'm considering writing a desktop client for my app in >>>>> the >>>>> future and that seems the easiest way to get the data to and >>>>> from the >>>>> desktop client. I haven't decided what that's going to look like >>>>> yet. >>>>> It looks like I may be hacking in a return value to return >>>>> extended >>>>> information to parent controller functions, like <title> tags. >>>>> but I >>>>> want to decide how it should work, first. It sounds like it's just >>>>> not a concern to the two biggest users of erlyweb >>>> >>>> If you want to contribute this feature (or any other feature that >>>> you >>>> think will be useful to other ErlyWeb users) I'll be happy to >>>> accept >>>> your code. >>>> >>>> Yariv >>>> >>>>> >>>>> >>>>>> >>>>>> Yariv >>>>>> >>>>>> On Nov 16, 2007 10:19 AM, David King <[EMAIL PROTECTED]> wrote: >>>>>>> >>>>>>> erlyweb uses a component system for rendering pages. It makes >>>>>>> most of >>>>>>> my controller functions return lists like this: >>>>>>> >>>>>>> [{data,post:title(Post)}, >>>>>>> {ewc,post,contents,[A,Post]}, >>>>>>> {ewc,comment,comments,[A,post:comments(Post)]}] >>>>>>> >>>>>>> The view function then looks like: >>>>>>> >>>>>>> <%@ show([Title,Contents,Comments]) %> >>>>>>> <h1><% Title %></h1> >>>>>>> <div class="post_contents"><% Contents %></div> >>>>>>> <ul class="comments><% Comments %></ul> >>>>>>> >>>>>>> I really like this, because it allows me to separate the view- >>>>>>> logic >>>>>>> for things like contents and comments out from each other, which >>>>>>> makes changing the behaviour of these quite simple, localised, >>>>>>> and >>>>>>> re- >>>>>>> useable. (In fact, as I re-write portions of erlyweb for my >>>>>>> purposes, >>>>>>> the component system is something that I haven't touched at all >>>>>>> because it works quite well.) However, it has an inherent >>>>>>> limitation: >>>>>>> none of those functions can return data to be rendered >>>>>>> outside of >>>>>>> their components. In my case, I'd like to be able to set <title> >>>>>>> tags, which means that the top-level controller function (by >>>>>>> top- >>>>>>> level, I mean the one referenced in the URL; like in /post/ >>>>>>> show/12, >>>>>>> the top-level controller function would be show/2) needs to >>>>>>> somehow >>>>>>> return information to be rendered outside its little sandbox. >>>>>>> >>>>>>> I see that Vimagi doesn't set <title> tags (neither <http:// >>>>>>> vimagi.com/p/0PXmMRe6hGV> nor <<a rel="nofollow" href="http://vimagi.com/users/">http://vimagi.com/users/</a> >>>>>>> feeling3_4> >>>>>>> set one, at least, and those are where I'd expect to see >>>>>>> them), but >>>>>>> BeerRiot does (<<a rel="nofollow" href="http://beerriot.com/beer/view/1751">http://beerriot.com/beer/view/1751</a>>; BTW I do >>>>>>> love >>>>>>> the idea of having a controller called "beer_controller"). >>>>>>> >>>>>>> It isn't limited to <title>s (for instance, I may want to >>>>>>> alert the >>>>>>> browser that an RSS equivalent of this page exists, or what the >>>>>>> caching TTL is for this page in the HTTP headers). Conceptually, >>>>>>> how >>>>>>> would one go about returning this extra information, while still >>>>>>> using the component system (I now have a lot of code that >>>>>>> uses it >>>>>>> that I'd like to not re-write :) )? >>>>>>> >>>>>>> >>>>>>> >>>>>>>> >>>>>>> >>>>>> >>>>>> >>>>> >>>>>> >>>>> >>>> >>>> >>> >>>> >>> >> >> > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "erlyweb" group. To post to this group, send email to erlyweb@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at <a rel="nofollow" href="http://groups.google.com/group/erlyweb?hl=en">http://groups.google.com/group/erlyweb?hl=en</a> -~----------~----~----~----~------~----~------~--~--- </pre> </div> <div class="msgButtons margintopdouble"> <ul class="overflow"> <li class="msgButtonItems"><a class="button buttonleft " accesskey="p" href="msg00134.html">Previous message</a></li> <li class="msgButtonItems textaligncenter"><a class="button" accesskey="c" href="index.html#00121">View by thread</a></li> <li class="msgButtonItems textaligncenter"><a class="button" accesskey="i" href="maillist.html#00121">View by date</a></li> <li class="msgButtonItems textalignright"><a class="button buttonright " accesskey="n" href="msg00123.html">Next message</a></li> </ul> </div> <a name="tslice"></a> <div class="tSliceList margintopdouble"> <ul class="icons monospace"> <li><ul> <li class="icons-email"><span class="subject"><a href="msg00107.html">[erlyweb-list] Re: <title>s and other non-component...</a></span> <span class="sender italic">David King</span></li> <li><ul> <li class="icons-email"><span class="subject"><a href="msg00110.html">[erlyweb-list] Re: <title>s and other non-compo...</a></span> <span class="sender italic">Yariv Sadan</span></li> <li><ul> <li class="icons-email"><span class="subject"><a href="msg00113.html">[erlyweb-list] Re: <title>s and other non-c...</a></span> <span class="sender italic">David King</span></li> <li><ul> <li class="icons-email"><span class="subject"><a href="msg00116.html">[erlyweb-list] Re: <title>s and other n...</a></span> <span class="sender italic">Yariv Sadan</span></li> <li class="icons-email"><span class="subject"><a href="msg00118.html">[erlyweb-list] Re: <title>s and other n...</a></span> <span class="sender italic">David King</span></li> <li class="icons-email"><span class="subject"><a href="msg00119.html">[erlyweb-list] Re: <title>s and other n...</a></span> <span class="sender italic">Yariv Sadan</span></li> <li class="icons-email"><span class="subject"><a href="msg00120.html">[erlyweb-list] Re: <title>s and other n...</a></span> <span class="sender italic">David King</span></li> <li class="icons-email"><span class="subject"><a href="msg00131.html">[erlyweb-list] Re: <title>s and other n...</a></span> <span class="sender italic">Yariv Sadan</span></li> <li class="icons-email"><span class="subject"><a href="msg00132.html">[erlyweb-list] Re: <title>s and other n...</a></span> <span class="sender italic">David King</span></li> <li class="icons-email"><span class="subject"><a href="msg00134.html">[erlyweb-list] Re: <title>s and other n...</a></span> <span class="sender italic">Yariv Sadan</span></li> <li class="icons-email tSliceCur"><span class="subject">[erlyweb-list] Re: <title>s and other n...</span> <span class="sender italic">David King</span></li> <li class="icons-email"><span class="subject"><a href="msg00123.html">[erlyweb-list] Re: <title>s and other n...</a></span> <span class="sender italic">Yariv Sadan</span></li> </ul></li> </ul></li> </ul></li> </ul></li> <li class="icons-email"><span class="subject"><a href="msg00108.html">[erlyweb-list] Re: <title>s and other non-component data</a></span> <span class="sender italic">Bryan Fink</span></li> </ul> </ul> </ul> </ul> </div> <div class="overflow msgActions margintopdouble"> <div class="msgReply" > <h2> Reply via email to </h2> <form method="POST" action="/mailto.php"> <input type="hidden" name="subject" value="[erlyweb-list] Re: <title>s and other non-component data"> <input type="hidden" name="msgid" value="F2F6488D-CA49-4B61-B9D9-FBA0758D47FA@ketralnis.com"> <input type="hidden" name="relpath" value="erlyweb@googlegroups.com/msg00121.html"> <input type="submit" value=" David King "> </form> </div> </div> </div> <div class="aside" role="complementary"> <div class="logo"> <a href="/"><img src="/logo.png" width=247 height=88 alt="The Mail Archive"></a> </div> <form class="overflow" action="/search" method="get"> <input type="hidden" name="l" value="erlyweb@googlegroups.com"> <label class="hidden" for="q">Search the site</label> <input class="submittext" type="text" id="q" name="q" placeholder="Search erlyweb"> <input class="submitbutton" name="submit" type="image" src="/submit.png" alt="Submit"> </form> <div class="nav margintop" id="nav" role="navigation"> <ul class="icons font16"> <li class="icons-home"><a href="/">The Mail Archive home</a></li> <li class="icons-list"><a href="/erlyweb@googlegroups.com/">erlyweb - all messages</a></li> <li class="icons-about"><a href="/erlyweb@googlegroups.com/info.html">erlyweb - about the list</a></li> <li class="icons-expand"><a href="/search?l=erlyweb@googlegroups.com&q=subject:%22%5C%5Berlyweb%5C-list%5C%5D+Re%5C%3A+%3Ctitle%3Es+and+other+non%5C-component+data%22&o=newest&f=1" title="e" id="e">Expand</a></li> <li class="icons-prev"><a href="msg00134.html" title="p">Previous message</a></li> <li class="icons-next"><a href="msg00123.html" title="n">Next message</a></li> </ul> </div> <div class="listlogo margintopdouble"> </div> <div class="margintopdouble"> </div> </div> </div> <div class="footer" role="contentinfo"> <ul> <li><a href="/">The Mail Archive home</a></li> <li><a href="/faq.html#newlist">Add your mailing list</a></li> <li><a href="/faq.html">FAQ</a></li> <li><a href="/faq.html#support">Support</a></li> <li><a href="/faq.html#privacy">Privacy</a></li> <li class="darkgray">F2F6488D-CA49-4B61-B9D9-FBA0758D47FA@ketralnis.com</li> </ul> </div> </body> </html> <script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'9d3e28352aa5554f',t:'MTc3MjA5NTQyOQ=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script>