[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:20071117" rel="nofollow">Sat, 17 Nov 2007 17:34:00 -0800</a></span> </p> </div> <div itemprop="articleBody" class="msgBody"> <!--X-Body-of-Message--> <pre> > I think that the best solution is to add a new return value, e.g. > {meta, Val}, to controller functions. ErlyWeb will accumulate those > values in a list and pass it to the 'phased' Fun as an extra > parameter. So, you could write > {phased, {ewc, A}, > fun(ExpandedEwc, MetaVals, Rendered) -> > {ewc, html_container, [A, MetaVals, Rendered]} > end}. > 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.</pre><pre> 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="msg00110.html">Previous message</a></li> <li class="msgButtonItems textaligncenter"><a class="button" accesskey="c" href="index.html#00113">View by thread</a></li> <li class="msgButtonItems textaligncenter"><a class="button" accesskey="i" href="maillist.html#00113">View by date</a></li> <li class="msgButtonItems textalignright"><a class="button buttonright " accesskey="n" href="msg00116.html">Next message</a></li> </ul> </div> <a name="tslice"></a> <div class="tSliceList margintopdouble"> <ul class="icons monospace"> <li class="icons-email"><span class="subject"><a href="msg00102.html">[erlyweb-list] <title>s and other non-component data</a></span> <span class="sender italic">David King</span></li> <li><ul> <li class="icons-email"><span class="subject"><a href="msg00104.html">[erlyweb-list] Re: <title>s and other non-component...</a></span> <span class="sender italic">Yariv Sadan</span></li> <li><ul> <li class="icons-email"><span class="subject"><a href="msg00105.html">[erlyweb-list] Re: <title>s and other non-compo...</a></span> <span class="sender italic">David King</span></li> <li><ul> <li class="icons-email"><span class="subject"><a href="msg00106.html">[erlyweb-list] Re: <title>s and other non-c...</a></span> <span class="sender italic">Yariv Sadan</span></li> <li><ul> <li class="icons-email"><span class="subject"><a href="msg00107.html">[erlyweb-list] Re: <title>s and other n...</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 ot...</a></span> <span class="sender italic">Yariv Sadan</span></li> <li><ul> <li class="icons-email tSliceCur"><span class="subject">[erlyweb-list] Re: <title>s an...</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>...</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>...</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>...</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>...</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>...</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>...</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>...</a></span> <span class="sender italic">Yariv Sadan</span></li> <li class="icons-email"><span class="subject"><a href="msg00121.html">[erlyweb-list] Re: <title>...</a></span> <span class="sender italic">David King</span></li> <li class="icons-email"><span class="subject"><a href="msg00123.html">[erlyweb-list] Re: <title>...</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-c...</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="B8CBB793-34DE-48C6-8D90-74BA5296AADD@ketralnis.com"> <input type="hidden" name="relpath" value="erlyweb@googlegroups.com/msg00113.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="msg00110.html" title="p">Previous message</a></li> <li class="icons-next"><a href="msg00116.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">B8CBB793-34DE-48C6-8D90-74BA5296AADD@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:'9d3f68f0ad67724e',t:'MTc3MjEwODU2Nw=='};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>