After trying almost every web framework for Ruby out there, I still could not find one I really liked (Wee was close, but has non-restful URLs), so I simply decided to grow my own (hey, you know me ;-)), called Rye.
Rye is a framework of the different kind. I don’t have a lot of code yet, and lacks a lot of functionality, but I could extract the basic idea already and will try to explain it here.
Rye provides an RESTful interface to stored objects. So far, my objects are simply stored as YAML files, but that will not scale for bigger amounts of data. Rye maps these objects onto URLs like this:
So far, Rye can handle the two most commonly used (and supported,
sigh) HTTP methods, GET and POST. In the case of GET, Rye will
retrieve/load the object, call the method on it (possibly with the
arguments and the parsed query) and, depending on the return value
of the method, render the generated page or call
show, the default
renderer for the object. POST is treated similary, except that the
object is saved to the store again before rendering the site.
Therefore, GET can’t easily change any values and is idempotent, as
required by REST. (Of course, you still can—and are free to—shoot
yourself in the foot by manipulating the storage on your own, but it
will really be your fault.)
The nice benefit of this is that there is not much to do to use Rye:
Usually (so far, at least) you simply define a few YAML specific
methods to store only the required instance variables of the object
and make your class inherit from
Rye::Base, which defines a few
helper methods and attributes (maybe this should get a mix-in).
As an example, I developed a very simple to-do list manager:
class ToDoList < Rye::Base attr_accessor :title attr_accessor :todo attr_accessor :done def initialize(title) super() @title = title @todo, @done = ,  end def to_yaml_properties; ["@title", "@todo", "@done"]; end def show; template; end def add(params); @todo << params["item"]; self; end def finish(item) @done << item if @todo.delete item self end def undo(item) @todo << item if @done.delete item self end end
As you can see, this is straight-forward Ruby code without any Web
specific stuff—except maybe the
show method that calls
a helper defined in
Rye::Base that renders the object using a
class-specific Kashmir template (of course, you can easily interface
with your favourite templating engine).
If you wonder why
self, well, that means
that Rye will redirect to
show them, a useful and logic convention.
undo do change data, and therefore need to be called
using POST. As of now, you would call
finish("blubb") by writing HTML
<form action="/myapp.rye/finish/blubb" method="post"> <input type="submit" value="Finish blubb!" /> </form>
If you decide to pass additional values (for example, to call
using a form) you can do that too, as usual:
<form action="/myapp.rye/add" method="post"> <input type="text" name="item" /> <input type="submit" value="Add!" /> </form>
Since the code essentially only contains the real application logic, it is very easy to unit test. In fact, you test it just like any other class. (Nevertheless, I may add a helper library for unit testing which I dub “ergot” :-))
So far, Rye is only about 150 lines of code, but already covers a lot of the basic functionality. I’ll need to add a generic store, so one can use databases (for example with Og) too and isn’t forced to use YAML. Maybe I get a first release done this week (or possibly not, who knows).
I’d be interested in hearing your comments on Rye, just comment here or mail me.
NP: 33hz—Digital Lover