From Aleksi.Niemela at cs.helsinki.fi Sat Jul 9 11:35:14 2005 From: Aleksi.Niemela at cs.helsinki.fi (Aleksi Niemela) Date: Sat Jul 9 11:28:05 2005 Subject: [Wee-talk] Nitro or Wee or NitroglyceWeen? Message-ID: <42CFEEB2.8060607@cs.helsinki.fi> Michael, as you seem to be somewhat active on Nitro front too I wonder what's Wee's future. Do you plan to keep it around and get it mature enough for production use (and a real contender on Rails/Nitro/what not web framework market)? Or do you plan to merge Wee functionality over Nitro and drop eventually abandon it altogether? I'm writing mid-size web app over Wee/Og combo, but I wonder if I should change the framework right now instead of ending up converting to Nitro at the end anyway. Wee is a nice pile of source code. I tend to read it's sources when I seek a bit of inspiration for clarity when my own expression of thoughts to code gets treadlocked. Thanks for the work done! - Aleksi From mneumann at ntecs.de Sun Jul 10 11:27:44 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Sun Jul 10 11:22:42 2005 Subject: [Wee-talk] Nitro or Wee or NitroglyceWeen? In-Reply-To: <42CFEEB2.8060607@cs.helsinki.fi> References: <42CFEEB2.8060607@cs.helsinki.fi> Message-ID: <42D13E70.1010101@ntecs.de> Hi, Aleksi Niemela wrote: > Michael, as you seem to be somewhat active on Nitro front too I wonder > what's Wee's future. Do you plan to keep it around and get it mature > enough for production use (and a real contender on Rails/Nitro/what not > web framework market)? Or do you plan to merge Wee functionality over > Nitro and drop eventually abandon it altogether? I think the core of Wee is pretty stable now and should be production quality. Classes such as Session or Application are still some kind of mess, but I'm slowly working on these issues. What I've recently done is, that it's now possible to integrate Wee components nearly seamlessly into Rails. Nitro support will follow soon. Basically I'll just using Nitro's session support. AFAIK, Nitro's session's can be distributed on multiple servers via DRb (as I've no need of this yet, I do not implement it in Wee myself ;-). Furthermore, using Nitro as base, one would gain the power of Nitro's shaders. For lots of problems, I still prefer the Wee-way. I do not plan to drop Wee, nor merge with any other project. Wee will stay there as a separate project, but George and I will cooperate more closely. For example next week, we'll both release our versions simultaneous (Wee 0.9.0 with lots of bug-fixes and a few features added). I've some Mewa-like meta-stuff implemented for Wee+Og (basically a quite advanced scaffolder), but I'm not yet sure whether this will flow into 0.9.0 as it needs some changes. In any case I could send you the raw sources, if you've some interest in it. > I'm writing mid-size web app over Wee/Og combo, but I wonder if I should > change the framework right now instead of ending up converting to Nitro > at the end anyway. Wee is a nice pile of source code. I tend to read > it's sources when I seek a bit of inspiration for clarity when my own > expression of thoughts to code gets treadlocked. Thanks for the work done! I'm currently implementing a mid-sized (more or less) web app in Wee/Og. My experience is, that if the application is very regular (it's easy for example to write a navigation component unless the page is too irregular), or is very dynamic, Wee is a good choice. Due to it's stateful nature, one must of course keep an eye on performance/memory issues when the number of users grow (I've not yet experienced any problems here). If you need bookmarking then Wee is of course not the best choice. It's possible to do some bookmarking but it's not that natural as it is in Nitro or Rails, and adds some extra complexity. The conclusion of that project is, that in my special case (which was pretty irregular), some parts would have been better implemented in Nitro, others in Wee. Especially page flow is IMHO better implemented using bookmarkable links (unless of course you need backtracking). Regards, Michael From Aleksi.Niemela at cs.helsinki.fi Sun Jul 10 17:24:38 2005 From: Aleksi.Niemela at cs.helsinki.fi (Aleksi Niemela) Date: Sun Jul 10 17:17:39 2005 Subject: [Wee-talk] How to forward directly in rendering phase Message-ID: <42D19216.9070502@cs.helsinki.fi> I wonder why it took so long before I hit this first time, but I spent almost two hours working out why my app suddenly stopped working. In the end it boils down to this example. Foo's callback works well, but Bar's wont jump right back! I don't expect to get @text into response, but I somehow expected to break Bar's rendering and jump over newly instantiated Foo but instead I'm getting nasty error message: # /lib/ruby/gems/1.8/gems/wee-0.8.0/lib/wee/core/component.rb:348:in `throw' /lib/ruby/gems/1.8/gems/wee-0.8.0/lib/wee/core/component.rb:348:in `call' lib/test/upshotter.rb:33:in `render' ... In session.rb there's a mentioning "Input callbacks should never call other components!" I guess the anchor hasn't input callback. But I also guessed Bar doesn't have it either. So, all in all, what's the "right way to do" forwarding to another class like Bar tries to do? And if the solution is trivial, like I hope it is, I blame last two hours :). - Aleksi module FooBar class Foo < Wee::Component def render r.h1 "Foo" r.anchor.callback{foo}.with("foo") end def foo call Bar.new("bar") # this works well end end class Bar < Wee::Component def initialize(text) super() @text = text end def render r.h1 "#{@text}" call Foo.new # and this doesn't end end end From mneumann at ntecs.de Mon Jul 11 04:47:57 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Mon Jul 11 04:42:48 2005 Subject: [Wee-talk] How to forward directly in rendering phase In-Reply-To: <42D19216.9070502@cs.helsinki.fi> References: <42D19216.9070502@cs.helsinki.fi> Message-ID: <42D2323D.3070604@ntecs.de> Aleksi Niemela wrote: > I wonder why it took so long before I hit this first time, but I spent > almost two hours working out why my app suddenly stopped working. In the > end it boils down to this example. Foo's callback works well, but Bar's > wont jump right back! I don't expect to get @text into response, but I > somehow expected to break Bar's rendering and jump over newly > instantiated Foo but instead I'm getting nasty error message: > > # > /lib/ruby/gems/1.8/gems/wee-0.8.0/lib/wee/core/component.rb:348:in `throw' > /lib/ruby/gems/1.8/gems/wee-0.8.0/lib/wee/core/component.rb:348:in `call' > lib/test/upshotter.rb:33:in `render' > ... > > In session.rb there's a mentioning "Input callbacks should never call > other components!" I guess the anchor hasn't input callback. But I also > guessed Bar doesn't have it either. > > So, all in all, what's the "right way to do" forwarding to another class > like Bar tries to do? And if the solution is trivial, like I hope it is, > I blame last two hours :). > > - Aleksi > > > module FooBar > > class Foo < Wee::Component > > def render > r.h1 "Foo" > r.anchor.callback{foo}.with("foo") > end > def foo > call Bar.new("bar") # this works well > end > end > > class Bar < Wee::Component > > def initialize(text) > super() > @text = text > end > > def render > r.h1 "#{@text}" > call Foo.new # and this doesn't How should the behaviour of Bar be? Should it render the h1-heading, then jump back to Foo.new? But then Foo.new would be displayed and not Bar. Or do you want to render Foo.new below the h1 heading? You can render components with: r.render Foo.new BTW, you example would result in a potential endless loop, as Foo calls Bar and Bar calls Foo. None of them ever returns (via. #answer). I'm not sure what you example should do. Maybe you can try to explain your intention. During #render you can't call other components, as calling a component modifies state, and rendering should not modify internal state (it should be reproducable). Regards, Michael From mneumann at ntecs.de Mon Jul 11 06:31:04 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Mon Jul 11 06:25:55 2005 Subject: [Wee-talk] Re: [Nitro] A Web Development Observation In-Reply-To: <200507110531.54129.dcorbin@machturtle.com> References: <200507110531.54129.dcorbin@machturtle.com> Message-ID: <42D24A68.6020708@ntecs.de> David Corbin wrote: > It's been almost two years since I've done any serious web-development in my > day job. I recently started a project at home to play with Rails, and > probably Og, if not Nitro. I've been reminded of what I hate most about web > development, and why I think it is generally such a slow process. > > You cannot trust the input being given. Ever. > > I'm not just talking about basic form validation. I mean you can't rely on > the order of a series of pages. You can't rely on cookies. You can't > believe that URLs are unmodified. You can't assume that any given URL will > only be clicked on once. It wears on you. > > I don't have any specific solution in mind, but if a framework were to > eliminate this concern from the developer, THAT would be a 100x productivity > boost. Hm, I think what you need is Wee ;-) Wee does not use URLs in the sense as other frameworks do. All state is kept on the server-side, so there's no way to modify the state from the client side. Actions (callbacks) are dynamic, that means, they can only be invoked after you have defined them, and only for that page for which they were defined. Example: r.anchor.callback { p "link clicked" }.with("click here") would display a click here tag. But you can only click on it from that page, where you register the callback above. A page is defined by the internal component state. Every time an action is performed, the component state is modified and as such a new page is created. In short: Callbacks are page-local. Or drop down lists: # select an object from these items items = [1, 2, "a string", {1 => 'hallo'}] # render it r.select_list(items).labels {|item| item.to_s}. callback {|choosen| p choosen} As 'items' is stored on the server-side, you can't malicously introduce any new values. Note that this way, you can use arbitrary objects from where you can choose from. What the user sees is given by #labels. This is truely one of Wee's strengths. http://rubyforge.org/projects/wee http://www.ntecs.de/viewcvs/viewcvs/*checkout*/Wee/trunk/doc/rdoc/index.html Regards, Michael From kaniemel at cs.helsinki.fi Mon Jul 11 11:18:30 2005 From: kaniemel at cs.helsinki.fi (K Aleksi Niemela) Date: Mon Jul 11 11:26:25 2005 Subject: [Wee-talk] Re: How to forward directly in rendering phase In-Reply-To: <42D2323D.3070604@ntecs.de> References: <42D19216.9070502@cs.helsinki.fi> <42D2323D.3070604@ntecs.de> Message-ID: Michael Neumann writes: > Aleksi Niemela wrote: >> Foo's callback works well, but Bar's >> wont jump right back! I don't expect to get @text into response, but I >> somehow expected to break Bar's rendering and jump over newly >> instantiated Foo but instead I'm getting nasty error message: >> >> So, all in all, what's the "right way to do" forwarding to another class >> like Bar tries to do? >> >> module FooBar >> >> class Foo < Wee::Component >> >> def render >> r.h1 "Foo" >> r.anchor.callback{foo}.with("foo") >> end >> def foo >> call Bar.new("bar") # this works well >> end >> end >> >> class Bar < Wee::Component >> >> def initialize(text) >> super() >> @text = text >> end >> >> def render >> r.h1 "#{@text}" >> call Foo.new # and this doesn't > > How should the behaviour of Bar be? > Should it render the h1-heading, then jump back to Foo.new? Like I tried to say, I don't expect Bar to render @text, but it really doesn't matter or hurt. What I expect to happen is that Bar (displays user text "bar" in browser or not) jumps over to page Foo again (which displays again "Foo" and a link). Effectively user would be clicking link "foo" and get a new page which immediately forwards again and lets he click foo again (and again). Should Bar#render has 'call Zak.new' instead I'd expect user see "foo" and click link "foo" after which he'd get to the page Zak (with or) without knowing he was very briefly at page to be rendered by Bar. So what I want is to know how to forward to a new page in method render! Like Bar tries to do but doesn't succeed due issued error. Should I render some kind of form which submit button's callback (in which forwarding works) forwards and some javascript magic to autoclick it when page loads effectively creating forwarding in #render? Or is there some other preferred way? Perhaps I should force creation of redirecting response in #render somehow and then just return from it. ---- As a background, you might have some insight how I should accomplish what I really want to do in more Weeish way. I try to setup the system to have few incoming "channels", ie. different urls. If this would be a blogging application the code would look something like: # forward incoming request by their url like # http://host/app/view/msg/10 or # http://host/app/edit/preferences/user/20 class Incoming < Wee::Component def initialize; super; end def render url = session.current_context.request.path # or something parts = url.split("/")[2..-1] case parts[0] when "view" case parts[1] when "msg" call MessageViewer.new(parts[2]) # ... when "edit" content, parameters = parts[1], parts[2..-1] call Editor.new(content, parameters) end end end It's my understanding that r.render Editor.new would not be enough as we actually want object Editor to have the ball from now on, ie. to forward control over. Another use of the pattern might be when trying to handle access control. Maybe there should be something like: class PreferencesEditor def render if session.user.has_access_for_functionality? "edit preferences" # user is allowed to edit preferences but might not have logged # in yet, his cookie might indicate who he is or perhaps # he has logged in as a normal user and need now to enlarge his # access rights for Administrator level if session.user.authenticated_for_functionality? "edit preferences" # normal rendition else if call Login.new(:functionality => "edit preferences") # normal rendition else # error: not suitable login even if there seems to be # access rights for the functionality end end else # error: no access for functionality end end end Thanks, - Aleksi From mneumann at ntecs.de Mon Jul 11 17:08:43 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Mon Jul 11 17:03:34 2005 Subject: [Wee-talk] Re: How to forward directly in rendering phase In-Reply-To: References: <42D19216.9070502@cs.helsinki.fi> <42D2323D.3070604@ntecs.de> Message-ID: <42D2DFDB.6070202@ntecs.de> K Aleksi Niemela wrote: > Michael Neumann writes: > >> Aleksi Niemela wrote: >> >>> Foo's callback works well, but Bar's wont jump right back! I don't >>> expect to get @text into response, but I somehow expected to break >>> Bar's rendering and jump over newly instantiated Foo but instead I'm >>> getting nasty error message: >>> So, all in all, what's the "right way to do" forwarding to another >>> class like Bar tries to do? >>> module FooBar >>> class Foo < Wee::Component >>> def render >>> r.h1 "Foo" >>> r.anchor.callback{foo}.with("foo") >>> end >>> def foo >>> call Bar.new("bar") # this works well >>> end >>> end >>> class Bar < Wee::Component >>> def initialize(text) >>> super() >>> @text = text >>> end >>> def render >>> r.h1 "#{@text}" >>> call Foo.new # and this doesn't >> >> >> How should the behaviour of Bar be? >> Should it render the h1-heading, then jump back to Foo.new? > > > Like I tried to say, I don't expect Bar to render @text, but it really > doesn't matter or hurt. What I expect to happen is that Bar (displays > user text "bar" in browser or not) jumps over to page Foo again (which > displays again "Foo" and a link). Effectively user would be clicking > link "foo" and get a new page which immediately forwards again and lets > he click foo again (and again). Call behaves very differently. What you want is "r.render component". In Wee, rendering and callback processing are two separate phases, which cannot be mixed. Imagine a page is displayed. Now you can click on an anchor, which triggers a callback to be invoked. This will modify the components state. In the next step, the component is rendered. This is done purely using the components state. > Should Bar#render has 'call Zak.new' instead I'd expect user see "foo" > and click link "foo" after which he'd get to the page Zak (with or) > without knowing he was very briefly at page to be rendered by Bar. > So what I want is to know how to forward to a new page in method render! > Like Bar tries to do but doesn't succeed due issued error. > Should I render some kind of form which submit button's callback (in > which forwarding works) forwards and some javascript magic to autoclick > it when page loads effectively creating forwarding in #render? Or is > there some other preferred way? Perhaps I should force creation of > redirecting response in #render somehow and then just return from it. > ---- > As a background, you might have some insight how I should accomplish > what I really want to do in more Weeish way. I try to setup the system > to have few incoming "channels", ie. different urls. If this would be a > blogging application the code would look something like: > > # forward incoming request by their url like > # http://host/app/view/msg/10 or > # http://host/app/edit/preferences/user/20 > class Incoming < Wee::Component > def initialize; super; end > def render > url = session.current_context.request.path # or something > parts = url.split("/")[2..-1] > case parts[0] > when "view" > case parts[1] > when "msg" > call MessageViewer.new(parts[2]) > # ... > when "edit" > content, parameters = parts[1], parts[2..-1] > call Editor.new(content, parameters) > end > end > end Take a look at my ComponentDispatcher: require 'set' class Wee::ComponentDispatcher < Wee::Component def initialize super() @rules = [] @components = Set.new end def add_rule(pattern, component, &block) @components.add(component) @rules << [pattern, component, block] end def do_render(rendering_context) if component = match(session.current_context.request.info) component.do_render_chain(rendering_context) end end def process_callbacks(&block) if component = match(session.current_context.request.info) component.process_callbacks_chain(&block) end end def backtrack_state(snapshot) snapshot.add(@__decoration) @components.each do |component| component.backtrack_state_chain(snapshot) end end protected def match(info) info ||= "" @rules.each do |pattern, component, block| if info =~ pattern block.call(component, $~) if block return component end end nil end end You can use it like: ############### comp = Wee::ComponentDispatcher.new comp.add_rule /calc/, Wee::Examples::Calculator.new comp.add_rule /pager\/(\d+)/, Wee::Pager.new(50) do |comp, match| comp.goto(Integer(match[1])) end comp.add_rule /(counter|)/, Wee::Examples::Counter.new ################ The block you give to add_rule are passed two arguments. The component (it's the same as the second argument to add_rule), and the MatchData object of the regular expression (first argument to add_rule). Inside the block you can modify the component state, in the case of a Pager component, you would set the current_page as shown above (method goto). Of course you have to create anchors that have the "pager/pagenum" inside it's URL. In Wee 0.9.0 you can do the following: r.anchor.info("pager/0").callback {....}.with(...) This will create URLs like /app/pager/0/___/session_id/page_id > It's my understanding that r.render Editor.new would not be enough as we > actually want object Editor to have the ball from now on, ie. to forward > control over. > Another use of the pattern might be when trying to handle access > control. Maybe there should be something like: > class PreferencesEditor > def render > if session.user.has_access_for_functionality? "edit preferences" > # user is allowed to edit preferences but might not have logged > # in yet, his cookie might indicate who he is or perhaps > # he has logged in as a normal user and need now to enlarge his > # access rights for Administrator level > if session.user.authenticated_for_functionality? "edit preferences" > # normal rendition > else > if call Login.new(:functionality => "edit preferences") > # normal rendition > else > # error: not suitable login even if there seems to be > # access rights for the functionality > end > end > else > # error: no access for functionality > end > end > end Take a look at my LoginDecoration: class Wee::LoginDecoration < Wee::Decoration def initialize(login_page) @login_page = login_page end def process_callbacks(&block) if logged_in? super else @login_page.process_callbacks_chain(&block) end end def do_render(rendering_context) if logged_in? super else @login_page.do_render_chain(rendering_context) end end def backtrack_state(snapshot) if logged_in? super else @login_page.backtrack_state_chain(snapshot) end end # Overwrite this method! def logged_in? raise "subclass responsibility" end end Just overwrite the logged_in? method and add the decoration to a component. Regards, Michael From mneumann at ntecs.de Mon Jul 11 17:23:13 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Mon Jul 11 17:18:02 2005 Subject: [Wee-talk] Re: How to forward directly in rendering phase In-Reply-To: <42D2DFDB.6070202@ntecs.de> References: <42D19216.9070502@cs.helsinki.fi> <42D2323D.3070604@ntecs.de> <42D2DFDB.6070202@ntecs.de> Message-ID: <42D2E341.8070907@ntecs.de> Michael Neumann wrote: > You can use it like: > > ############### > comp = Wee::ComponentDispatcher.new > comp.add_rule /calc/, Wee::Examples::Calculator.new > comp.add_rule /pager\/(\d+)/, Wee::Pager.new(50) do |comp, match| > comp.goto(Integer(match[1])) > end better change that to: comp.add_rule /pager\/(\d+)/, Wee::Pager.new(50) do |c, match| c.goto(Integer(match[1])) end > comp.add_rule /(counter|)/, Wee::Examples::Counter.new > ################ Regards, Michael From Aleksi.Niemela at cs.helsinki.fi Mon Jul 11 17:28:32 2005 From: Aleksi.Niemela at cs.helsinki.fi (Aleksi Niemela) Date: Mon Jul 11 17:21:14 2005 Subject: [Wee-talk] Re: How to forward directly in rendering phase Message-ID: <42D2E480.9020208@cs.helsinki.fi> Michael Neumann wrote: > K Aleksi Niemela wrote: > >> Like I tried to say, I don't expect Bar to render @text, but it >> really doesn't matter or hurt. What I expect to happen is that Bar >> (displays user text "bar" in browser or not) jumps over to page Foo >> again (which displays again "Foo" and a link). Effectively user would >> be clicking link "foo" and get a new page which immediately forwards >> again and lets he click foo again (and again). > > > Call behaves very differently. What you want is "r.render component". > In Wee, rendering and callback processing are two separate phases, > which cannot be mixed. Imagine a page is displayed. Now you can click > on an anchor, which triggers a callback to be invoked. This will > modify the components state. In the next step, the component is > rendered. This is done purely using the components state. > No, I guess I don't want divert rendering to a subcomponent, or that is what I have understood r.render to do before continuing rendering the rest. I want to break rendering, and forward directly to another "page" which should (process callback of which there are none and) start rendering that. class Foo def initialize ... def render r.anchor.callback { call AnotherPage.new } # moves control over to another component call YetAnotherPage.new # doesn't move control and should be replaced with some construct That construct might intercept current_context.response and replace it with RedirectResponse to a page to be rendered by YetAnotherComponent. That construct might be "hidden" form which would get autosubmitted by javascript immediately when user's browser gets it and effectively does what the title of the thread: forwards directly in rendering phase. Maybe it should be some other construct as at least the latter one seems to be a bit hackish by nature :) > Take a look at my ComponentDispatcher: > This looks very interesting, even though I don't quite understand it. I'm especially interested in this code > comp.add_rule /pager\/(\d+)/, Wee::Pager.new(50) do |comp, match| > comp.goto(Integer(match[1])) > end > Namely, what is #goto? That's probably the answer to my call for direct forwarding to some other component in rendering phase. I didn't find it from 0.8.0 code nor was it in your example code for ComponentDispatcher. The LoginDecorator looked interesting as well! I'll look into that. Looking forward for 0.9.0. - Aleksi From mneumann at ntecs.de Mon Jul 11 17:43:15 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Mon Jul 11 17:38:05 2005 Subject: [Wee-talk] Re: How to forward directly in rendering phase In-Reply-To: <42D2E44E.302@cs.helsinki.fi> References: <42D19216.9070502@cs.helsinki.fi> <42D2323D.3070604@ntecs.de> <42D2DFDB.6070202@ntecs.de> <42D2E44E.302@cs.helsinki.fi> Message-ID: <42D2E7F3.4040607@ntecs.de> Aleksi Niemela wrote: > Michael Neumann wrote: > >> K Aleksi Niemela wrote: >> Take a look at my ComponentDispatcher: >> > This looks very interesting, even though I don't quite understand it. > I'm especially interested in this code > >> comp.add_rule /pager\/(\d+)/, Wee::Pager.new(50) do |comp, match| >> comp.goto(Integer(match[1])) >> end >> > Namely, what is #goto? That's probably the answer to my call for direct > forwarding to some other component in rendering phase. I didn't find it > from 0.8.0 code nor was it in your example code for ComponentDispatcher. #goto is not what you want ;-) pager = Wee::Pager.new pager.current_page = 5 # equivalent to: pager.goto(5) The interesting parts are in process_callbacks, do_render and backtrack_state. It's hard to explain what's going on. You have to understand how Decorations work. Basically, you can decorate components. A simple example are the PageDecoration or the FormDecoration. All they do is to wrap the components' #render method within a or
tag. But the same can be done for the process_callbacks or backtrack_state methods. A decoration can prohibit that process_callbacks is called for the component (or more precise, the processing of the decoration chain is aborted at this point). > The LoginDecorator looked interesting as well! I'll look into that. > Looking forward for 0.9.0. Tomorrow ;-) Regards, Michael From cjs at cynic.net Mon Jul 11 21:42:06 2005 From: cjs at cynic.net (Curt Sampson) Date: Mon Jul 11 21:37:03 2005 Subject: [Wee-talk] Re: [Nitro] A Web Development Observation In-Reply-To: <42D24A68.6020708@ntecs.de> References: <200507110531.54129.dcorbin@machturtle.com> <42D24A68.6020708@ntecs.de> Message-ID: On Mon, 11 Jul 2005, Michael Neumann wrote: > Wee does not use URLs in the sense as other frameworks do. While the ability to look more like a local application is one of Wee's strengths, one of its weaknesses is that it more or less destroys the concept of a URI. The Universal Resource Identifier no longer universally identifies a resource. One of the side effects of this is that bookmarks no longer work. I've been wondering if there's some way to fix this while still preserving Wee's strong points. I.e., if I have an application keeping track of items from a catalogue, is it possible to make wee work such that the URI /catalogue/item/171323 will always display the current information for item 171323 (or whatever it's allowed to display about item 171323 given the authorization available from whatever authentication credentials I've previously presented)? Ideally, this would even be displayed in the location bar. Does it even make sense to do this? Or do you just not write applications like that in wee? cjs -- Curt Sampson +81 90 7737 2974 http://www.NetBSD.org Make up enjoying your city life...produced by BIC CAMERA From dcorbin at machturtle.com Mon Jul 11 19:35:52 2005 From: dcorbin at machturtle.com (David Corbin) Date: Tue Jul 12 03:52:22 2005 Subject: [Wee-talk] Re: [Nitro] A Web Development Observation In-Reply-To: <42D24A68.6020708@ntecs.de> References: <200507110531.54129.dcorbin@machturtle.com> <42D24A68.6020708@ntecs.de> Message-ID: <200507111935.52322.dcorbin@machturtle.com> On Monday 11 July 2005 06:31 am, Michael Neumann wrote: > David Corbin wrote: > > It's been almost two years since I've done any serious web-development in > > my day job. I recently started a project at home to play with Rails, and > > probably Og, if not Nitro. I've been reminded of what I hate most about > > web development, and why I think it is generally such a slow process. > > > > You cannot trust the input being given. Ever. > > > > I'm not just talking about basic form validation. I mean you can't rely > > on the order of a series of pages. You can't rely on cookies. You can't > > believe that URLs are unmodified. You can't assume that any given URL > > will only be clicked on once. It wears on you. > > > > I don't have any specific solution in mind, but if a framework were to > > eliminate this concern from the developer, THAT would be a 100x > > productivity boost. > > Hm, I think what you need is Wee ;-) > Thanks. I'll take a look at it, but I'd be it would also need to support certain "direct" entry points, which might be in an email or bookmarkable. > > Regards, > > Michael From mneumann at ntecs.de Tue Jul 12 04:15:02 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Tue Jul 12 04:09:52 2005 Subject: [Wee-talk] Re: [Nitro] A Web Development Observation In-Reply-To: References: <200507110531.54129.dcorbin@machturtle.com> <42D24A68.6020708@ntecs.de> Message-ID: <42D37C06.8030304@ntecs.de> Curt Sampson wrote: > On Mon, 11 Jul 2005, Michael Neumann wrote: > >> Wee does not use URLs in the sense as other frameworks do. > > > While the ability to look more like a local application is one of Wee's > strengths, one of its weaknesses is that it more or less destroys > the concept of a URI. The Universal Resource Identifier no longer > universally identifies a resource. One of the side effects of this is > that bookmarks no longer work. Correct. > I've been wondering if there's some way to fix this while still > preserving Wee's strong points. I.e., if I have an application keeping > track of items from a catalogue, is it possible to make wee work such > that the URI > > /catalogue/item/171323 > > will always display the current information for item 171323 (or whatever > it's allowed to display about item 171323 given the authorization > available from whatever authentication credentials I've previously > presented)? Ideally, this would even be displayed in the location bar. In Wee 0.9.0 this is possible! But then, you're limited to more or less one "main" component per page, as the URI is only able to give some information to one component. It works like shown below: class CatalogComponent < Wee::Component attr_accessor :item_no ... end disp = Wee::ComponentDispatcher.new disp.add_rule /catalogue\/item\/(\d+)/, CatalogComponent.new do |c, md| c.item_no = Integer(md[1]) end # add further rules here... Keep in mind, that now, your anchor tags within CatalogComponent should look like: r.anchor.info("catalogue/item/#{ new_item_no }").callback .... By default, all links will leave the current URI as is. > Does it even make sense to do this? Or do you just not write > applications like that in wee? A few guys are just trying to do that with Wee. I've some other ideas to do this in a more transparent way, so that you don't have to modify all your links. Basically, each component would have a method: def collect_for_url(params) params['item_no'] = @item_no end And the resulting hash would then be converted into an URL by a central method. In the same way, a fetch_from_url method would be called, where each component can take some state from the URL (the central method would in the same way extract the hash from the URL). Regards, Michael From mneumann at ntecs.de Tue Jul 12 05:40:32 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Tue Jul 12 05:35:25 2005 Subject: [Wee-talk] [ANN] Wee 0.9.0 - Nitro/Rails integration Message-ID: <42D39010.6070403@ntecs.de> Hi, I'm proud to release Wee 0.9.0. Lots of refactorings, bug fixes and new features, most notably the integration of Wee into Nitro and Rails, which means, that you can put Wee components into your existing Nitro or Rails applications (for more information, read section Nitro/Rails integration below). WHAT is Wee? It's a framwork for very dynamic, component-oriented, stateful web applications, largely inspired by Seaside. See [1] and [2] for further information. To get started quickly: # Install Wee: gem install wee # Write your first example irb > require 'rubygems' > require 'wee' > > class HelloWorld < Wee::Component > def render > r.h1 "Hello World!" > r.anchor.callback{@flag = !@flag}.with(@flag ? 'ON' : 'OFF') > end > end > > Wee.run(HelloWorld) # Now point your browser at http://127.0.0.1:2000/app Have Fun! Regards, Michael ======================================================================== == New components ======================================================================== * Wee::ComponentDispatcher For an example see examples/dispatcher.rb. This allows bookmarkable URLs like /catalog/item/171323 to be used with Wee. class CatalogComponent < Wee::Component attr_accessor :item_no ... end catalog = CatalogComponent.new d = Wee::ComponentDispatcher.new d.add_rule(/catalogue\/item\/(\d+)/, catalog) do |c, md| c.item_no = Integer(md[1]) end # add further rules here... Keep in mind, that now, your anchor tags within CatalogComponent should look like: r.anchor.info("catalogue/item/#{ new_item_no }").callback .... By default, all links will leave the current URI as is. * Wee::LoginDecoration You just need to overwrite it's logged_in? method and add it to your components that need access controll. * Wee::Pager * Wee::Examples::Counter You need to require 'wee/examples/counter' * Wee::Examples::EditableCounter You need to require 'wee/examples/editable_counter' * Wee::Examples::Calculator You need to require 'wee/examples/calculator' ======================================================================== == Changes in Html renderer ======================================================================== * r.label # => * r.hidden_input # => * r.anchor.info(info_url) # => * Added support for radio buttons (methods r.new_radio_group and r.radio_button) * You can now use #value of textarea fields instead of #with. * Implemented r.form.onsubmit_update method * Method Brush::SelectListTag#selected takes optionally a block. In this case, only those elements will be selected, for which the block evaluates to true. This allows us to use some custom compare functions instead of the default ones '==' or 'include?'. * Method Brush::SelectListTag#labels also might be passed a block, in which case the label is the return value of the block called with the corresponding item as parameter. * Added class Brush::CheckboxTag and corresponding methods HtmlCanvas#check_box and alias #checkbox. * Method HtmlCanvas#paragraph is no longer a single tag. It can now contain other tags, e.g. like

. * Added method HtmlCanvas#multiline_text, which replaces newline characters (\n) in the text with
tags. ======================================================================== == Changes in Templating ======================================================================== * Added :local option, with which one can specify a template file relative to the component file, e.g: class MyComponent < Wee::Component template :render_this, :local => 'this.tmpl' end Futhermore, added an :r_as_param option, which generates a render method that takes a renderer object as parameter 'r'. ======================================================================== == New Examples ======================================================================== * examples/dispatcher.rb * examples/nitro/* * examples/demo.rb * examples/radio.rb ======================================================================== == Nitro/Rails integration ======================================================================== Wee can now be used from within Nitro or Rails, but it's functionality is still limited (may change in future releases). A brief example using Nitro+Wee: require 'wee' require 'wee/adaptors/nitro' require 'wee/examples/calculator' require 'nitro' require 'nitro/contoller' class AppController < Nitro::Controller include Wee::Nitro::ControllerMixin scaffold_with_component do Wee::Examples::Calculator.new. add_decoration(Wee::FormDecoration.new). add_decoration(Wee::PageDecoration.new('Hello from Wee/Nitro!')) end end Nitro.run(:host => '127.0.0.1', :port => 9999, :dispatcher => Nitro::Dispatcher.new('/app' => AppController)) Now point your browser to http://127.0.0.1:9999/app/index. An example how to use Rails+Wee follows (most stuff applies to Nitro as well): ## # In config/environment.rb add: require 'wee' require 'wee/adaptors/rails' require 'components/mycomponent' ## # In components/mycomponent.rb: class MyComponent < Wee::Component # ... your Wee component ... end ## # In app/controllers/wee_controller.rb: class WeeController < ApplicationController include Wee::Rails::ControllerMixin register_component "my" do MyComponent.new end end ## # In app/views/index.rhtml: <%= show_component 'my' %> Of course you can render as many components as you like on one page. You can create components dynamically at runtime with: make_component component_name, component_object For example instead of using 'register_component' in the WeeController shown above, you could write: def index make_component('my', MyComponent.new) unless has_component?('my') # render the view end If you don't need the component anymore, drop it: drop_component 'my' If you want to map 1:1 a Wee::Component to an ActionController, you can use: class WeeController < ApplicationController include Wee::Rails::ControllerMixin scaffold_with_component do MyComponent.new end end At the moment, only pageless mode is possible, so no backtracking is performed. NOTE: Your Wee components must be fully marshallable to work with Rails CGI mode. That means, you are not allowed to use continuations, and no code blocks (callbacks). For example instead of: r.anchor.callback { answer true } You have to write: r.anchor.callback(:answer, true) Or more general: r.anchor.callback(Wee::LiteralMethodCallback.new(self, :answer, true)) ======================================================================== [1]: http://rubyforge.org/projects/wee [2]: http://www.ntecs.de/viewcvs/viewcvs/*checkout*/Wee/trunk/doc/rdoc/index.html From Aleksi.Niemela at cs.helsinki.fi Wed Jul 13 16:27:17 2005 From: Aleksi.Niemela at cs.helsinki.fi (Aleksi Niemela) Date: Wed Jul 13 16:22:09 2005 Subject: [Wee-talk] Patch: wee-0.9.0 og/session.rb to work with recent Og Message-ID: <42D57925.6030401@cs.helsinki.fi> I believe Og API changed at some point 0.19.0 or so. This seems to work for me against Og 0.20.0. - Aleksi $ diff -u session.rb~ session.rb --- session.rb~ 2005-07-12 18:54:59.581125000 +0300 +++ session.rb 2005-07-13 23:22:28.346750000 +0300 @@ -1,9 +1,9 @@ class OgSession < Wee::Session def awake - application.db.get_connection + application.db.get_store end def sleep - application.db.put_connection + application.db.put_store end end From Aleksi.Niemela at cs.helsinki.fi Wed Jul 13 17:20:14 2005 From: Aleksi.Niemela at cs.helsinki.fi (Aleksi Niemela) Date: Wed Jul 13 17:15:00 2005 Subject: [Wee-talk] Bug for mutual #call? Message-ID: <42D5858E.8080501@cs.helsinki.fi> Does this expose a bug or a feature (or my poor understanding)? I somehow expect mutual calls to work. I'd use them to avoid creating new objects which have to initialize. As a real-world use for this consider following case. Imagine Foo initializes by fetching dozens of dozens of digits long numbers from database and checks which of those are in fact primes. Then Bar would show some interesting properties of primes and it should allow one to get back to list of primes fast. One shouldn't use #answer as Bar might not have been called by Foo, but whichever component it was who called Bar it knew Foo, the precalced primes list holder. This mutually calling code fails with following error message when one tries to get back from Bar page. # /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:60:in `backtrack_state' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/component.rb:239:in `backtrack_state_chain' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:113:in `backtrack_state' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/component.rb:239:in `backtrack_state_chain' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:113:in `backtrack_state' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:60:in `backtrack_state' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/component.rb:239:in `backtrack_state_chain' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:113:in `backtrack_state' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/component.rb:239:in `backtrack_state_chain' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:113:in `backtrack_state' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:60:in `backtrack_state' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/component.rb:239:in `backtrack_state_chain' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:113:in `backtrack_state' /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/component.rb:239:in `backtrack_state_chain' - Aleksi $LOAD_PATH << "/lib/ruby/gems/1.8/gems/wee-0.9.0/lib" require 'wee' require 'wee/adaptors/webrick' require 'wee/utils' module FooBar class Foo < Wee::Component def initialize(bar = nil) super() @bar = bar end def render r.h1 "Foo" r.anchor.callback do @bar = Bar.new(self) unless @bar call @bar end.with("bar") end end class Bar < Wee::Component def initialize(foo) super() @foo = foo end def render r.h1 "Bar" r.anchor.callback do call @foo end.with("foo") end end end if $0 == __FILE__ then app = Wee::Utils.app_for { FooBar::Foo.new } Wee::WEBrickAdaptor.register('/app' => app).start(:Port => 2012) end From mneumann at ntecs.de Wed Jul 13 18:44:41 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Wed Jul 13 18:39:28 2005 Subject: [Wee-talk] Bug for mutual #call? In-Reply-To: <42D5858E.8080501@cs.helsinki.fi> References: <42D5858E.8080501@cs.helsinki.fi> Message-ID: <42D59959.9060203@ntecs.de> Aleksi Niemela wrote: > Does this expose a bug or a feature (or my poor understanding)? I > somehow expect mutual calls to work. I'd use them to avoid creating new > objects which have to initialize. I believe it's neither a bug nor feature. > As a real-world use for this consider following case. Imagine Foo > initializes by fetching dozens of dozens of digits long numbers from > database and checks which of those are in fact primes. Then Bar would > show some interesting properties of primes and it should allow one to > get back to list of primes fast. One shouldn't use #answer as Bar might > not have been called by Foo, but whichever component it was who called > Bar it knew Foo, the precalced primes list holder. Why not use #answer? I think your interactions between components are too complex! Don't use call as a "goto" (you know, goto considered harmfull ;-). Use it like calling a subroutine, don't introduce cycles (at least not for the same object!). See below how to solve your problem. Anyway, I'd try to make the interactions between both components non recursive. > This mutually calling code fails with following error message when one > tries to get back from Bar page. > > # > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:60:in > `backtrack_state' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/component.rb:239:in > `backtrack_state_chain' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:113:in > `backtrack_state' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/component.rb:239:in > `backtrack_state_chain' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:113:in > `backtrack_state' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:60:in > `backtrack_state' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/component.rb:239:in > `backtrack_state_chain' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:113:in > `backtrack_state' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/component.rb:239:in > `backtrack_state_chain' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:113:in > `backtrack_state' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:60:in > `backtrack_state' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/component.rb:239:in > `backtrack_state_chain' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/decoration.rb:113:in > `backtrack_state' > /lib/ruby/gems/1.8/gems/wee-0.9.0/lib/wee/core/component.rb:239:in > `backtrack_state_chain' > > - Aleksi > > > > $LOAD_PATH << "/lib/ruby/gems/1.8/gems/wee-0.9.0/lib" > > require 'wee' > require 'wee/adaptors/webrick' > require 'wee/utils' > > module FooBar > > class Foo < Wee::Component > def initialize(bar = nil) > super() > @bar = bar > end > def render > r.h1 "Foo" > r.anchor.callback do > @bar = Bar.new(self) unless @bar > call @bar replace with: call @bar, proc {|res| call res} > end.with("bar") > end > end > > class Bar < Wee::Component > def initialize(foo) > super() > @foo = foo > end > > def render > r.h1 "Bar" > r.anchor.callback do > call @foo replace with: answer @foo Regards, Michael From mneumann at ntecs.de Wed Jul 13 18:45:23 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Wed Jul 13 18:40:18 2005 Subject: [Wee-talk] Patch: wee-0.9.0 og/session.rb to work with recent Og In-Reply-To: <42D57925.6030401@cs.helsinki.fi> References: <42D57925.6030401@cs.helsinki.fi> Message-ID: <42D59983.70401@ntecs.de> Aleksi Niemela wrote: > I believe Og API changed at some point 0.19.0 or so. This seems to work > for me against Og 0.20.0. Thanks! Will fix this. Regards, Michael From Aleksi.Niemela at cs.helsinki.fi Thu Jul 14 01:46:06 2005 From: Aleksi.Niemela at cs.helsinki.fi (Aleksi Niemela) Date: Thu Jul 14 01:40:50 2005 Subject: [Wee-talk] Bug for mutual #call? In-Reply-To: <42D59959.9060203@ntecs.de> References: <42D5858E.8080501@cs.helsinki.fi> <42D59959.9060203@ntecs.de> Message-ID: <42D5FC1E.3020202@cs.helsinki.fi> Michael Neumann wrote: > Why not use #answer? I think your interactions between components are > too complex! Don't use call as a "goto" (you know, goto considered > harmfull ;-). Use it like calling a subroutine, don't introduce cycles > (at least not for the same object!). > I was thinking real world behavior is quite complex. It's easy for me to see how to use call-answer -pattern in subroutine like fashion. I don't see how to make it work with Amazon type of service where you get to so many different pages from each of the pages, where people flow around before nailing down their liking, add objects of interest to shopping cart, clean it now and then, before finally proceeding checkout (which is quite process like). If I envision following types of pages, could you show what's the Wee (or Seaside) way to decompose functionality and setup pages and calling structure: - welcome screen - object categories - category's object browsing - object details - search results - shopping cart - "One-Click" checkout On all pages also - search - usually same, but sometimes different navigation: breadcrumbs and menu-like - recommendations in all pages - some kind of view to your of shopping cart (sometimes there are more room for it) From all pages you can get to all pages! Also one should be able to bookmark most of the pages, so incoming to the system will be mostly from direct jumps in instead of browsing through welcome screen. Both of these requirements make the whole page structure pretty goto-like for me, but probably I've not just seen the light. Is this something that's already well described for Seaside. Or should we CC that mailing list also? Thanks for your answer! > See below how to solve your problem. Anyway, I'd try to make the > interactions between both components non recursive. Thanks, I will try it, and probably it will do. It's interesting to note that there was no problem before I wanted to "reuse" earlier instances of pages. Just doing call Page.new() worked all the time, but of course caused creation of new instance with it's initializations. Then I hit on pages which do quite a bit of initialization and will halt the server should there be more than a few simultaneous users. - Aleksi From mneumann at ntecs.de Thu Jul 14 05:29:35 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Thu Jul 14 05:24:21 2005 Subject: [Wee-talk] Bug for mutual #call? In-Reply-To: <42D5FC1E.3020202@cs.helsinki.fi> References: <42D5858E.8080501@cs.helsinki.fi> <42D59959.9060203@ntecs.de> <42D5FC1E.3020202@cs.helsinki.fi> Message-ID: <42D6307F.4010809@ntecs.de> Aleksi Niemela wrote: > Michael Neumann wrote: > >> Why not use #answer? I think your interactions between components are >> too complex! Don't use call as a "goto" (you know, goto considered >> harmfull ;-). Use it like calling a subroutine, don't introduce cycles >> (at least not for the same object!). >> > I was thinking real world behavior is quite complex. It's easy for me to > see how to use call-answer -pattern in subroutine like fashion. I don't > see how to make it work with Amazon type of service where you get to so > many different pages from each of the pages, where people flow around > before nailing down their liking, add objects of interest to shopping > cart, clean it now and then, before finally proceeding checkout (which > is quite process like). You don't need #call to change the current page! Simply use a component in front of your pages which delegates to the currently active page. This component is known to all pages, so to change to a different page, you'd simply: a.anchor.callback { @main.set_active_page = 'cart' } @main would store a Hash, e.g. {'cart' => CartComponent.new}. > If I envision following types of pages, could you show what's the Wee > (or Seaside) way to decompose functionality and setup pages and calling > structure: > > - welcome screen > - object categories > - category's object browsing > - object details > - search results > - shopping cart > - "One-Click" checkout > > On all pages also > - search > - usually same, but sometimes different navigation: breadcrumbs and > menu-like > - recommendations in all pages > - some kind of view to your of shopping cart (sometimes there are more > room for it) All those common things like searching, shopping cart or recommendations could be done with components which are included into the top-level pages. > From all pages you can get to all pages! Also one should be able to > bookmark most of the pages, so incoming to the system will be mostly > from direct jumps in instead of browsing through welcome screen. Use the ComponentDispatcher class for the top-level pages. > Both of these requirements make the whole page structure pretty > goto-like for me, but probably I've not just seen the light. Hm, goto is okay here ;-) But goto and call are different! Don't use call when you never plan to return. > Is this something that's already well described for Seaside. Or should > we CC that mailing list also? They probably know more about those issues, so feel free to CC. > Thanks for your answer! > >> See below how to solve your problem. Anyway, I'd try to make the >> interactions between both components non recursive. > > > > Thanks, I will try it, and probably it will do. It's interesting to note > that there was no problem before I wanted to "reuse" earlier instances > of pages. Just doing call Page.new() worked all the time, but of course > caused creation of new instance with it's initializations. Then I hit on > pages which do quite a bit of initialization and will halt the server > should there be more than a few simultaneous users. The problem is that #call adds a decoration in front of the component that delegates to the called component. If you do the same for the second component, this delegates back to the calling component, which delegates to the called component which... a loop! Regards, Michael From Aleksi.Niemela at cs.helsinki.fi Mon Jul 18 19:28:00 2005 From: Aleksi.Niemela at cs.helsinki.fi (Aleksi Niemela) Date: Mon Jul 18 19:22:36 2005 Subject: [Wee-talk] Right way to utilize cookies? Message-ID: <42DC3B00.1020808@cs.helsinki.fi> What's the right way to use cookies? Currently I write something like session.current_context.response.cookies << WEBrick::Cookie.new("user_id", user_id) This doesn't work out. It does place the cookie but does simultaneous so that there's no use as I don't know how to read it back. Basically the cookie gets associated with a specific url which has always the session and callback information at the end of it. Next time the same page is loaded in new session (or even in same session) the url isn't the same so the Cookie is at user's browser but won't be sent thus not received and so it's not accessible at server side anymore. Also this way is bad as it will litter browser's cookie store with a new cookie with each page view (that is url). How should I write out cookies that would be accessible in next sessions? Please note also that I'd end up using WEBrick code even though entire thing might be run under some other web server (Apache). But I guess that's tolerable. - Aleksi From mneumann at ntecs.de Tue Jul 19 04:56:41 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Tue Jul 19 04:51:18 2005 Subject: [Wee-talk] Right way to utilize cookies? In-Reply-To: <42DC3B00.1020808@cs.helsinki.fi> References: <42DC3B00.1020808@cs.helsinki.fi> Message-ID: <42DCC049.8010802@ntecs.de> Aleksi Niemela wrote: > What's the right way to use cookies? Currently I write something like > > session.current_context.response.cookies << > WEBrick::Cookie.new("user_id", user_id) > > This doesn't work out. It does place the cookie but does simultaneous so > that there's no use as I don't know how to read it back. Basically the > cookie gets associated with a specific url which has always the session > and callback information at the end of it. Next time the same page is > loaded in new session (or even in same session) the url isn't the same > so the Cookie is at user's browser but won't be sent thus not received > and so it's not accessible at server side anymore. Also this way is bad > as it will litter browser's cookie store with a new cookie with each > page view (that is url). Take a look at lib/wee/pageless/session.rb and lib/wee/adaptors/webrick.rb. This are the two places where cookies are used and written out. I guess you should set the #path attribute of the cookie to request.build_url(:request_handler_id => nil, :page_id => nil) This will remove the session-id and the page-id part of the URL. > How should I write out cookies that would be accessible in next sessions? > > Please note also that I'd end up using WEBrick code even though entire > thing might be run under some other web server (Apache). But I guess > that's tolerable. Due to using the Wee::Request class, this should work with other adaptors as well (as long as it's implemented ;-). Regards, Michael From Aleksi.Niemela at cs.helsinki.fi Tue Jul 19 17:06:16 2005 From: Aleksi.Niemela at cs.helsinki.fi (Aleksi Niemela) Date: Tue Jul 19 17:00:53 2005 Subject: [Wee-talk] Place for logging Message-ID: <42DD6B48.6020004@cs.helsinki.fi> I'm sure there's some perfect place to inject page traversing logging among other important activities logging. But where would it be best? If I'd use ComponentDispatcher that would be obvious place, but perhaps I should attach to rendering loop and push important event to the log from there? - Aleksi From mneumann at ntecs.de Tue Jul 26 17:55:35 2005 From: mneumann at ntecs.de (Michael Neumann) Date: Tue Jul 26 17:49:59 2005 Subject: [Wee-talk] Place for logging In-Reply-To: <42DD6B48.6020004@cs.helsinki.fi> References: <42DD6B48.6020004@cs.helsinki.fi> Message-ID: <42E6B157.7060401@ntecs.de> Aleksi Niemela wrote: > I'm sure there's some perfect place to inject page traversing logging > among other important activities logging. But where would it be best? What exactly do you want to accomplish? Write out a log event every time a page is accessed? You would best do this in class Wee::ComponentRunner (lib/wee/core/componentrunner.rb). Regards, Michael