Riding the Waves of a new Ruby Web Framework
The popularity of Ruby has lead to the creation of such web frameworks as Ruby on Rails, Merb and Camping, among others. A new web framework known as Waves was recently released which has some features that should attract Ruby developers to give it a try.
Waves, like Ruby on Rails, is an MVC framework and uses what is referred to as Request Lambdas, where each mapping consists of a rule and block. When a rule matches a request, the block is run. This is one of the unique features of Waves.
Waves other nice features include:
- True Code Reloading
- Hot Patching
- Cluster Support
- Thread Safety
InfoQ had the opportunity to chat with the creator of Waves, Dan Yoder, about the framework.
Robert Bazinet (RB): So what is Waves?
Dan Yoder (DY): Waves is a next-generation Web apps framework, MIT licensed. It picks up where Rails left off, basically, which is what makes it "next generation." Some of this is basic stuff, like being thread-safe and having a smaller footprint. Some of it is taking DRY to the next level with features like JITR (Just In Time Resources), which makes it much easier to reuse your MVC code across applications, or even reuse entire applications (because, among other things, applications are encapsulated within modules). Waves is much more open and extensible, as well. For example, you can easily write your own View class to change the way views are selected or rendered, or use a different database platform for models (the default is Ruby Sequel). It has the same basic idea as Rails - MVC for Web applications in Ruby - but builds on the experience of using Rails, which I did for several years, to create an even more powerful framework.
RB: Why did you create it?
DY: The short answer; Camping.
Longer answer; Mostly because I had reached some hard limits of Rails in my own applications. Waves actually began life as an extensive set of plug-ins. However, I never really got to the point where I wanted to release them because, in effect, I found I was building a new framework that just sat on top of Rails. It was more like Streamlined than an ordinary plug-in. I also found I was by-passing or monkey-patching bits of Rails code, essentially changing the expected behavior of the framework, so it didn't necessarily play well with others in the Rails world. A great example of this was my initial implementation of Just In Time Resources: ActiveDependency overrides const_missing in Object and Module to handle code reloading. I wanted to change this behavior and so I had to then override what Rails was doing. I didn't like that solution because I had a solution that didn't require touching Object or Module, but I was stuck because that was how Rails did it.
Then one day I was looking at Camping. I don't remember why, I just remember that I was amazed at how concise the code was. That was when the light-bulb went on that it might actually be simpler just to create a new framework that had the features I wanted, without having to work around Rails. It was a difficult decision because I had been planning on releasing the stuff I'd done as an add-on to Rails somehow, which is much less of an uphill battle. Plus, there was a lot of code I had to rewrite. So that was painful. But in the end I think the resulting code was much leaner and easier to extend and work with. Then Ben over at DuckTyped.com pointed me to Rack, which had come out while I was buried in code, and that basically clinched it. At the same time, DataMapper and Sequel were maturing, which really made it possible to introduce a full-featured framework that could be completely focused on just the MVC Web app part of the problem.
RB: How old is Waves?
DY: I only started work on Waves in August of '07. The first beta release was the beginning of February. So it is a very new framework, just sort of starting out on its journey. I'm old school: beta, to me, means "not ready for production use."
RB: What is the best way for developers to be able to try out and find out more about writing applications utilizing Waves?
DY: There is a screen-cast that is probably the best starting point, which follows a tutorial that you can also go through if the screen cast captures your imagination. There are reasonably complete RDocs as well. There's a support forum, too, and I try to respond to any questions within a few hours, or at most, a day. So you can go through the tutuorial and then maybe start playing around with it, based on what's in the RDocs, and check the forums and ask questions if you get stuck.
RB: Waves is an MVC framework as is Rails. How is Waves different than Rails?
DY: Myriad ways. Like I said, it is "next generation," an evolution of Rails. It's thread-safe and has a smaller footprint. It is much more focused on reuse, both within applications and across them: JITR, encapsulating applications within modules, and so on. The equivalent of routes are Request Lambdas, which are much more powerful and allow you to color outside the MVC lines when it makes sense. They also allow you to secure an application across all controllers in one place. Models can bind to any ORM framework you like, but if you don't use one at all, you don't pay a price for using one in terms of memory usage and performance. For example, I have a Waves-based CMS that uses file storage and really doesn't need an ORM. Waves has first-class views which are decoupled much more from the controller than in Waves. Layouts, for example, are specified within the view itself, not the controller. Similarly, you can nest layouts or invoke controller methods from within views. Another really crucial difference is that Waves allows for true code reloading. That is, code is automatically unloaded before it is reloaded, so that there are no artifacts left-over from the prior loads. The importance of this is that debugging is a bit easier, but also that you can hot patch production code reasonably safely using LiveConsole. That's a good sample of the differences. It's really an evolution of the MVC paradigm within Ruby.
RB: What types of sites are running Waves?
DY: I have a CMS that powers a variety of sites that I've done, including, of course, the Ruby Waves site, RubyWaves.com. There is a also a theme building application I've done in Waves. These were both originally running on Rails and now they run on Waves. They take up about a third to a quarter as much memory as they used to, and the code base is smaller than it was in Rails. They've also run for weeks without needing a restart. So I'm encouraged by that. I'd love to get some other data points, though, from others. Hopefully, that will happen soon.
RB: Is Waves open source? If so, how can developers get involved?
DY: Waves is MIT-licensed, which is about as liberal as it gets. I am really eager to bring on some core contributors to help move the platform forward. The first step to getting involved is just to ping me on the support forums and let me know what kinds of things you'd like to work on. Right now, it's wide open. There is a ton of stuff to do and I don't think Waves, or really any significant framework, can succeed without a community of developers working on it. As it stands already, Waves has benefited tremendously from the existence of Rack, Sequel, and Markaby. That is a ton of work that has been, in effect, off-loaded to some really great open-source efforts. That allows Waves to focus on being really, really good at just helping provide the MVC glue. But there is still a lot of opportunity to make it better.
RB: Waves is thread-safe, can you explain?
DY: Waves supports a thread-per-request model and the request processing occurs within a mutex so that different threads don't stomp on each other. Since Waves supports clustering and uses Rack, this isn't the only model that is supported, but I think it is important to give developers the choice, especially since Ruby 1.9 will support native OS threads. Right now, threads aren't very cool within the Ruby community but once native threading is supported, I suspect they will make a comeback because they will get way faster. The benefits are that you can scale with fewer instances of your application running, especially on machines that have good threading implementations that can take advantage of parallel architectures. And Waves makes it pretty simple to take advantage of that.
RB: How do you see this working with Ruby 1.9, seeing 1.9 has "native" threads?
DY: I should be clear that presently Waves is unsupported on 1.9. However, that is a major objective for Waves going forward, not only because 1.9 has a lot of nice features that Waves can take advantage of, but obviously because being thread-safe will make it possible for Waves to make a quantum leap in performance on 1.9. That is one of the reasons that I haven't worried as much about performance as, say, the Merb folks have. Plus, in the next release, you should be able to run Waves on Thin to get better performance. But I think it will get much more interesting once we move to 1.9.
RB: What is your JRuby support like? Waves uses Sequel which is not 100% supported in JRuby?
DY: That is probably after 1.9 support on the roadmap, though I am open to suggestions. I should point out that Waves does not depend on Sequel, it is just the default for a new application. But, that said, I am more focused on features right now than performance, so JRuby is not an immediate priority. I really liked the feature mix in Sequel, so that is a good example of that. Hopefully, what will happen is that the key libraries for Waves will migrate to 1.9 and JRuby soon enough for our roadmap. Again, feedback from the Ruby community can change things, especially if someone is interested in contributing (Hint, hint!)
RB: Can you give us some details on your plans for Waves?
DY: Well, first, I've already gotten some great suggestions from folks, including adding support for the Tenjin, Haml, and Sass templating libraries and the Thin Web server, which will be available very soon. Plus, a bug fix for the clustering support. I also plan to add support for database-backed sessions, which is currently missing, and make some enhancements to the request lambdas.
There is a big effort needed to enhance the schema reflection capabilities for Waves. This is a weak point for Sequel and DataMapper at the moment, and I'd like Waves to have some notion of an ORM-independent schema, because I think reflection is crucial to extending the JIT principal to Views.
I'd like to figure out what the best default approach should be for testing. I've used a variety of approaches and really like RSpec, but I hesitate to build that into the default Waves application because there are so many different opinions and approaches to testing right now within the Ruby community. Sequel was a much easier decision because it has support for migrations and because it allows Ruby expressions as queries, which I think is a really cool feature; but I am not as confident in making RSpec a default. So help in that area would be awesome.
I'd also like to start working on performance, initially just by doing some benchmarking and profiling to see where there might be problems. Really, there is just a ton of interesting stuff to do. I think Waves is pretty cool already, but part of what makes it cool is what it makes possible. What's there is just the tip of the iceberg. I am maintaining a list of roadmap items, which is still in the early stages of refinement, at http://rubywaves.com/roadmap if people are interested in more details.
RB: Dan, thank you for taking the time to speak with me about Waves.
The Waves website has a tutorial on creating a blog in multiple parts. I was able to spend the time to setup Waves and run through the tutorials and it all worked as advertised and created a nice application. A screencast which follows along with the tutorial is also available. Additional information about Waves can be found on the Waves website.