The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Comparing the underlying models of Wee and Rails

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Michael Neumann

Posts: 66
Nickname: backflash
Registered: May, 2003

Michael Neumann is fallen in Love with Ruby
Comparing the underlying models of Wee and Rails Posted: Feb 26, 2005 4:54 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Michael Neumann.
Original Post: Comparing the underlying models of Wee and Rails
Feed Title: Mike's Weblog
Feed URL: http://www.ntecs.de/blog-old/index.rss?cat=ruby&count=7
Feed Description: Blogging about Ruby and other interesting stuff.
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Michael Neumann
Latest Posts From Mike's Weblog

Advertisement
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.

Read: Comparing the underlying models of Wee and Rails

Topic: &#8216;They won&#8217;t ever fit together like Rails&#8217; Previous Topic   Next Topic Topic: Soo many quotes, so little space

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use