7. April, 2009
in
»
»
by Michael Neumann

Around 4 years have passed since the last release of Wee.

What is Wee?

Wee is a Seaside-inspired 1 web-framework for building highly-dynamic component-based web-applications.

What’s new?

  • 100% Rack based
  • Support for continuations
  • JQuery AJAX support
  • Ruby 1.9 ready

Distinctive Features

Wee is not just another web framework. It is completely different.

Continuations

You can use continuations to model the page flow of the your application, in the same way as you’d call a method in a GUI application. Continuations are optional; nothing in Wee depends on them. Example:

# you can write code like this:

if callcc YesNoMessageBox.new('Really?')
  # do something
else
  # something else
end

Without continuations one has to use (ugly) Continuation Passing Style (CPS):

call YesNoMessageBox.new('Really?') do |res|
  if res
    # do something
  else
    # something else
  end
end

Backtracking

Backtracking means that the user can naturally use the browsers back button despite Wee’s statefulness. This is not taken for granted for stateful web frameworks. Behind the scenes, Wee keeps multiple states of the application around with only little help by the programmer.

Components

Contrary to the widely used model/view/controller (MVC) paradigm, Wee tighly couples the controller and the view within a component. Components itself are highly decoupled from the rest of the application and can be reused to construct more complex applications. The powerful programmatic HTML rendering approach further reduces wasting the programmers mind by avoiding switching files (controller/view) or languages (Ruby/HTML). Therefore in Wee everything is written in Ruby. The programmatic HTML renderer is not just a simple HTML builder, it provides very powerful methods for easily generating HTML constructs and registering callbacks. Example:

#
# Generating a <select> tag
#

# select an object from these items
items = [1, 2, 3, 4]

# the labels shown to the user
labels = items.map {|i| i.to_s}

# render it
r.select_list(items).labels(labels).callback {|choosen| p choosen}

# render a multi-select list, with objects 2 and 4 selected
r.select_list(items).multi.labels(labels).selected([2,4])

Call/Answer mechanism

From callback handlers you can call other components which in turn replace the current components view. The called component can later return (or answer) back to the calling componenent. Example:

class YesNoMessageBox < Wee::Component
  def initialize(msg)
    super()
    @msg = msg
  end

  def render(r)
    r.bold(@msg)
    r.form do
      r.submit_button.value('YES').callback { answer true }
      r.space
      r.submit_button.value('No').callback { answer false }
    end
  end
end

# Use call (or callcc) as in the Continuation section above
# to call a component:
call YesNoMessageBox.new('Really?')

The classical Hello World Example

require 'rubygems' if RUBY_VERSION < "1.9"
require 'wee'

class HelloWorld < Wee::Component
 def initialize
   super
   add_decoration Wee::PageDecoration.new(title="Hello World")
 end

 def render(r)
   r.h1 "Hello World from Wee!"
   r.div.onclick_callback { p "clicked" }.with("click here")
 end
end

Wee.run(HelloWorld) if __FILE__ == $0
# Now point your browser to http://localhost:2000/

Installation

gem install wee

More Resources

  • http://rubyforge.org/projects/wee

  • http://www.ntecs.de/projects/wee/doc/rdoc/

  • http://github.com/mneumann/wee

25. February, 2009
in
»
»
by Michael Neumann

The last couple of days I spent refactoring my web application framework Wee, a Seaside-like framework for Ruby that I started back in 2004 with a lot of mental help from Avi Bryant (one of the main guys behind Seaside). It’s now approaching a 2.0 release. Wee is now fully Rack based (Rack is a commonly used Ruby Webserver Interface) and the code is in general even cleaner than it was before (huge parts were rewritten). Plus one cool feature: Continuations.

Continuations

Yesterday I finally thought it’s time to put back in continuations mainly because of some very interesting developments (i.e. patches) for Ruby 1.8.x, which seems to fix memory leaks that occured when using continuations.

Continuations in Wee were never used as extensively as they were used in Seaside. And it’s interesting to read that Seaside 2.8 reduced heavy usage of continuations – something that Wee did from the beginning :)

An example says more than thousands words, so here we go:

require 'wee'

class Page < Wee::Component
  def initialize
    add_decoration Wee::PageDecoration.new('Title')
    super
  end
  def render(r)
    r.anchor.callback {
      if callcc YesNoMessageBox.new('Really delete?')
        callcc InfoMessageBox.new('Deleted!')
      else
        callcc InfoMessageBox.new('Deleted action aborted')
      end
    }.with("delete?")
  end
end

class InfoMessageBox < Wee::Component
  def initialize(msg)
    @msg = msg
    super()
  end

  def render(r)
    r.h1(@msg)
    r.anchor.callback { answer }.with('OK')
  end
end

class YesNoMessageBox < InfoMessageBox
  def render(r)
    r.h1(@msg)
    r.anchor.callback { answer true }.with('YES')
    r.space(1)
    r.anchor.callback { answer false }.with('NO')
  end
end

Wee.runcc(Page)

The interesting part of this example is the anchor tag callback handler of component Page. When clicked it will display a YES/NO message box which will return true if you clicked on YES, otherwise false. When it returns, execution resumes exactly at the point after the callcc call. In fact, callcc returns the return value of the called component. A called component returns by calling the answer method (it behaves mostly like the regular return statement). The concrete mechanism how this all works out is a bit more complicated as it involves installing and removing several decorations to delegate rendering and catch exceptions upon answer, but this is totally unrelated to continuations.

So how would it look without the use of continuations? Well, the callback handler would turn from:

if callcc YesNoMessageBox.new('Really delete?')
  callcc InfoMessageBox.new('Deleted!')
else
  callcc InfoMessageBox.new('Deleted action aborted')
end

into:

call YesNoMessageBox.new('Really delete?') do |res|
  if res
    call InfoMessageBox.new('Deleted!')
  else
    call InfoMessageBox.new('Deleted action aborted')
  end
end

Actually in this concrete example it’s not hard to rewrite the code without using continuations. But for more complex examples it would get much worse. For example, using continations, a simple sequential flow like the following one:

callcc page1
callcc page2
callcc page3

would turn into the much less readable equivalent using CPS (“continuation passing style”):

call page1 do
  call page2 do
    call page3
  end
end

Which one would you prefer? The good thing: In Wee you can use both, that’s why I have the two methods call and callcc, the latter not to mix up with Kernel.callcc.

Performance and Memory Usage

The reason why continuations were basically unsupported in Wee for a very long time was that they leaked memory. Since a few months there circulated patches on the ruby-core mailing list that seem to fix those leaks. Actually the reason seams to be that some parts of the stack are not overwritten when calling a function and as such old values keep referenced: a leak is born! I haven’t tried those patches, but I think they work. Instead I tried Ruby 1.9.1. And wow! It’s incredible! Memory usage stays constant at 12 MB, regardless of the number of requests. And performance scales nearly linearily as I increase the number of threads.

For 10000 requests (with one thread) Ruby 1.9.1 takes 16 seconds and requires 12 MB of memory. The same example with Ruby 1.8.7 grows to 329 MB of memory and takes 56 seconds. That’s an increase in performance of factor 3.5 and a 27-fold reduction of memory.

The example I’m using for the benchmark is the following 2-level nested callcc component call:

class Benchmark < Wee::Component

  #
  # calls Called2 then returns
  #
  class Called1 < Wee::Component
    def render(r)
      r.anchor.callback { callcc Called2.new; answer }.with('back')
    end
  end

  class Called2 < Wee::Component
    def render(r)
      r.anchor.callback { answer }.with('back')
    end
  end

  def render(r)
    r.anchor.callback { callcc Called1.new }.with("click")
  end
end

Conclusion

Continuations seem to be stable enough and not too expensive in terms of memory and performance in Ruby 1.9 so that there is nothing against using them (wisely) within Wee. This makes Wee the only web framework for Ruby to my knowledge that uses continuations. Coupled with other great features provided by Wee, for example reusable components, backtracking or the programmatic HTML generation, this undoubtly allows Wee to be called one of the most advanced web application frameworks for Ruby. Worth to note is that Wee does not focus on RESTful multi-million page-view serving, scaling applications. Instead Wee focuses on very complex applications, similar as found in traditional GUIs, and to get the job done quick and beautiful.

7. February, 2008
7. February, 2008
in
»
»
by Michael Neumann

I wrote an implementation of the Arc Challenge in Ruby using my web-framework Wee. The sourcecode is available here. I haven’t used continuations, because I think I broke continuation support in some of the later versions of Wee (just because I haven’t used continuations in my Wee apps). Once Rubinius gets (even) more mature, and my spare time allows, I’d like to get back to some ideas of Wee and make use of continuations.

28. February, 2005
28. February, 2005
in
»
»
by Michael Neumann
I can’t write all Wee code on my own. So here is a list of things that needs to be done:
  • Make session-id cookies available to both Wee::Request and Wee::PagelessRequest, controlled by an application-wide setting.
  • Finish the implementation of pretty-URLs (this rulez!). Thanks to Joao Pedrosa who is working on this.
  • Implement a FilterDecoration and it’s subclass AuthorizationDecoration (that’s very easy, ~20 lines of code).
  • Implement a Seaside-like root_for traversal, which allows each component in the tree to add stuff inside the <head> tag. This is triggered by the root-component from it’s render method.
  • Refactor the Wee::Session class and it’s subclasses.
  • Implement further adaptors, most useful would be a FastCGI adaptor. This would need to factor out the WEBrick dependent parts.
  • Implement ResouceHandlers, which make it possible to generate images (or other external resources) from within your components.
  • Use it in your projects and write tutorials ;-)
26. February, 2005
26. February, 2005
in
»
»
by Michael Neumann
I’m trying to marry my child Wee with some of Rails features, mainly REST-like, pretty URLs. But before, I have to understand the differencies in how they work.

Disclaimer: This is my understanding of how Rails work. I might be wrong.

Rails

Rails model is very simple compared to that of Wee. The controller class and the method to invoke is extracted directly from the URL. For example:

/blog/show

would invoke BlogController#show. Now imaging the following URL:

/blog/show/4

This would invoke BlogController#show with @params = {‘id’ => 4}. I don’t know how Rails knows that 4 maps to the ‘id’ key, but that’s another story.

So you have these parts of a URL:

/controller/action/arguments

In Rails, there’s also no (conceptual) distinction between performing an action and rendering, as is the case in Wee. Both are inseparable from each other (in Rails).

Another difference to Wee is, that the controller classes are stateless, and instances of it might be reused (pooling). On the other hand this implicates that you can’t store information inside a controller instance across requests.

Wee

In Wee, we differenciate between an action phase, where callbacks are invoked and as such possibly modify the state of components, and a render phase, which ideally is side-effect free and whose sole purpose is to render the component to HTML (or whatever format you like).

Imagine you look at a simple Wee application which displays an HTML anchor tag. If you click on that anchor, you’ll trigger an action phase, which eventually will find the registered callback associated with the anchor you have clicked on and invokes it. At the end of the action phase, Wee will forward you to a new (automatically generated) URL, which when requested by your browser, will trigger the render phase. This in turn renders the whole component tree. "Why redirect", you might ask. Well, this simply avoids that the same callback will be invoked again if you hit your browsers reload button. Whenever you hit on reload, this will only trigger a render phase event.

Additionally, at the end of each action phase, a snapshot of the component tree is taken, so that you can go back to older states (called back-tracking). The information about which state of the component tree we refer to, is stored as page_id inside the URL. This page_id increases whenever an action phase is performed.

So, an URL in Wee basically consists of the following parts:

session_id page_id [callback_id]

where callback_id is optional. If it is given, the URL triggers an action phase. Otherwise, a render phase.

Compared to Rails controllers, Wee’s components are composites, meaning that they may contain sub-components which itself might contain sub-components and so on. And in Wee there’s only ever one root component, whereas in Rails there are usually multiple controllers. All this makes it nearly impossible to have REST-like URLs in Wee. Also due to the reason that a sub-component cannot be rendered on it’s own, whereas a controller in Rails builds a whole page. So it does not make sense to have URLs in Wee like:

/1.2.3
# == @root_component.children[1].children[2].children[3]

Marrying Wee and Rails aproaches

The concept of multiple top-level controllers can be easily added onto Wee by using the following RootComponent class:

# NOTE: not fully functional code!

class RootComponent < Wee::Component
  def initialize
    super()
    @controllers = {
      'blog' => add_child(BlogComponent.new),
      'list' => add_child(ListComponent.new)
    }
  end

  def render
    controller = # extract information from URL
    r.render @controllers[controller]
  end
end

This RootComponent merely acts as a dispatcher. It looks at the URL and extracts the desired controller out of it and then forwards to it.

Likewise, we could map the Rails action part (the "show" in "/blog/show"), to invoke render_xxx (e.g. render_show) of the controller-component (I use this term now, to distinguish it from a "regular" Wee component and to mark the similarity with a Rails controller):

  def render
    controller = # extract information from URL
    action = # extract Rails action part from URL

    component = @controllers[controller]

    component.with_renderer {
      component.send("render_" + action)
    }
  end

And even further, we could also extract the additional arguments of the URL for use inside the called render method. We could use a custom parse_arguments method here in each controller-component.

Now lets look at a simple example:

class BlogController < Wee::Component
  def parse_arguments(str)
    # for /blog/show/5, str would be "5"
    @params = ...   # e.g. {'id' => 5}
  end

  def render_show
    entry = BlogEntry.get(@params['id'])
    # render it
  end

  def render_list
    BlogEntry.find_all do |entry|
      # render it
    end
  end
end

What else would be needed is to tell which controller/action pair should be used. This could for example be specified each time when generating an anchor or form tag:

r.anchor.controller('blog/show/5').callback { .... }.with('show')

Note that this would first invoke the callback and then render ‘blog/show/5’. Of course you could ommit in this case the callback. But specifying the controller/action pair each time is tedious, as this would have to be done in each sub-component, too, which completely breaks the concept of a component. So the second approach is much better:

r.anchor.callback {
  ... do something
  request.controller = 'blog/show/5'
}

where the request.controller setting is carried inside the URL as long as you assign a new value to it.

Note that you can still use sub-components with this approach, but they would no longer be subject of REST-like URLs.

1. February, 2005
1. February, 2005
in
»
»
by Michael Neumann
Read yourself here.
26. January, 2005
12. September, 2007
in
»
»
by Michael Neumann
This night, I hacked up a Table and a Pager component for Wee. The Table component is 140 lines of code (including all HTML generation, nothing else except CSS styles are required), the Pager is 100 lines long.

Some days ago, I wrote an OgScaffolder component. It’s damn easy to use. Just pass an Og domain class to OgScaffolder.new, and what you get is a regular Wee component. Look at the screenshot below.

Below I’d like to show some Nemo screenshots, to show it’s potential. Note that the whole generic editor component (the first screenshot) is less than 200 lines very clean Ruby code! Thanks Kevin ;-)

24. November, 2004
24. November, 2004
in by Michael Neumann
I’m playing around with DragonFly's checkpointing support. Many thanks to Matt Dillon, who now made a syscall:

leaf.dragonflybsd.org/mailarchive/users/2004-11/msg00191.html

I wrote a Ruby wrapper around the sys_checkpoint syscall. You can find the sources here: www.ntecs.de/viewcvs/viewcvs/DragonFly/checkpoint/

The next step is to put this into the Wee sources, so that you can shutdown and reload Wee applications that use continuations. Of course, this only works on DragonFlyBSD. But I don’t think this is much of a problem…

31. October, 2004
12. September, 2007
in
»
»
by Michael Neumann
As my dad is giving a guest lecture about the mathematics behind building society savings (Bausparen) at University of Karlsruhe, he wanted to give his students some tools they can play with easily.

Last evening, we then build the calculator shown in the picture below. It’s a portable web application using Ruby and my new Wee framework. I spent most time on generating the diagram (it’s done using gnuplot). The rest was straightforward, once we had the underlying calculations working.

The total code size is 360 lines of code (including HTML), of which 110 are used for the calculation and for generating the diagram. Lots of lines of code are currently spent in conversion and validation routines (german number format).

You can try it out online here: ntecs.de/wee/ehf/