Category Archives: Rails

Alternatives to Model-Based Validation?

Rails has an decent set of validation rules for its database models. You can specify that particular variables must be present or satisfy certain constraints, either by themselves (“must be two characters long”) or in relation to each other (“password can’t be blank for administrators”). I’ve written several of my own extensions to these for validating phone numbers, email addresses, tracking numbers, and the like.

It works fine, at first. But model-based validation breaks down in several situations. Here are a few examples:

1. Wizard-like interfaces break the rules. By definition, a wizard decomposes the process into several steps. Your model objects are often invalid until you finish the last step. I have yet to see a solution to this. Most people end up adding some sort of knowledge about the wizard to the model’s validation code (“If I’m only asking for the person’s name and address right now, don’t try to validate his email address”).

2. In Rails, you can’t save your models unless they satisfy all of the validity conditions. This problem probably won’t arise at first, but as your code base evolves, it can have some nasty side-effects. Like when a user can’t change his password, because the model has lately been changed to require a variable that used to be optional.

Seaside itself provides nothing to help you with validation. Search some archives and you’ll find people recommending Magritte, which is a metadata descriptor system for model objects. It was written by Lukas Renggli, who is one of the lead developers of Seaside itself.

Magritte improves the problematic situations above in a couple of significant ways. For one, Magritte descriptions can be configured on any object, not just on database models. In Seaside, a wizard is likely to be implemented with several components (one per page), so a corresponding model could be built with just the validation rules it needs. Additionally, Magritte is completely separate from your persistence layer, so you are free to save your model objects regardless of whether Magritte’s validation rules are satisfied.

But I’m still not satisfied with the approach. Model-based validation has a bad smell to me, though in some limited ways I am sure it is useful. But the more I look at systems that work this way, the more I see what looks like UI-specific code in the model. Should your model really be concerned whether the user has entered matching strings for “password” and “password confirmation”? What if I want to use real first-class objects to represent a phone number? Validation should happen before the data ever gets to the model. It strikes me that validation belongs in the form, not in the model. In Seaside, that means that validation would happen at the component level.

So I’m looking for a better way. How are others handling validation in Seaside? Beyond that, how do other frameworks help with form validation? The most intriguing thing I’ve seen so far is the “newforms” framework in Django, which couples form inputs to their validation.

It seems that this would be fairly easy to implement in Seaside. You could use blocks to make its behavior pluggable. If you end up using one particular form in several places, make your own subclass of Form and reuse it. Or if you only need it once, build the Form instance programmatically.

Are there any other frameworks that provide validation hooks but are not model-based?

Advertisements

5 Comments

Filed under Rails, Seaside

My Full-Circle Journey Back to Smalltalk

I suppose it’s time to tell my story. I was a Smalltalk zealot in the late 90’s, but I left it behind when I started my own business. I’ve now come full-circle, and I’m finding once again that Smalltalk is the best tool for most of the programming work I do.

I learned Smalltalk programming from Travis Griggs while working at Key Technology. He mentored me in Smalltalk and other general programming methods, and I introduced him to Linux. Travis likes to give me more credit than I deserve for some of the work that we did together, but one thing was certain: we had a blast working together.

Key went through a difficult aquisition, and I spent most of my energy working to bring our two software teams to common ground. My wife and I travelled back and forth between Medford, Oregon and our home in Walla Walla (with our newborn son, our first) while I worked with developers in both locations. Diplomacy is not something I particularly enjoy, but I’m good at it and the team really needed somebody in that role.

But the end result was that I didn’t get much time to do any significant programming. The more time passed, the more I missed it. I didn’t get to work with Travis as much anymore, and our team was becoming fractured as our project list grew. Despite all of my efforts to bring people together, our team was dissolving under the increasing project load.

I had always wanted to work from home, and I was becoming burned out in my Key position, so I left Key and took up consulting work. Most of my clients needed web applications, so I became a web developer.

I built my first web applications in Smalltalk. Travis and I had written the original WikiWorks code, and I used our experience there to build my own HTTP 1.1 server. This later became the basis for the Swazoo server, which was built on my code at Camp Smalltalk 2000 in San Diego. I implemented my own Smalltalk Active Pages (abbreviated SAP, to distinguish them from ASP sites) and built several sites using them.

At the time, there wasn’t much web application work being done in the Smalltalk world, and the frameworks people were developing were unattractive to me. I had to support myself, from top to bottom, and this was starting to feel painful.

This was what drew me towards PHP, Apache, and PostgreSQL. The promise of safety in numbers was attractive — I would never have to wonder if my server was fully compliant with the HTTP specs. But the main attraction for me was PHP’s support for for various open source libraries. PHP made it easy to handle image uploads in multiple formats, draw custom graphs, and build other visuals on the fly. Editing PHP apps in vim was easier over low-bandwidth connections (like a cell phone data connection) than making a VNC connection to a headful server image, too.

So I left Smalltalk behind and built a few large PHP apps. Nearly all of them relied heavily on PHP’s graphics library bindings for generation of custom reports and editable page components. I built content management systems that let my customers edit their page titles, for example, and behind the scenes PHP would generate new navigation buttons from template PNGs and TrueType fonts. Another app managed a database of donors for a non-profit radio network and allowed call-center volunteers to easily enter pledges from supporters — while the studio crew saw up-to-the-minute totals on their screens.

Things went smoothly at first but got rougher as the applications got bigger. I made heavy use of the flimsy object model in PHP 4 and built my own object-relational layer, and this helped me survive as long as I did. But I grew increasingly frustrated as I tried to scale my PHP applications. There was no way around the ugliness of the code.

seaside.jpgAt that time, somebody pointed me at one of the early versions of Seaside. I had taken a look at Seaside a few years ago, and while it looked interesting, I confess that I didn’t get it. I saw how call: and answer: worked to give you a certain level of modalism in your application, but that was all I saw. The Seaside HTML writers were less mature then, too, and that was a deterrent to me. I liked being able to interleave PHP and HTML code in template files, but that was mostly because my pages didn’t use CSS effectively.

I missed the larger picture, so I went back to PHP.

When Ruby on Rails started to gain popularity, it was like a breath of fresh air to me. Rails is a very clean framework for web applications, and it required no paradigm shift. Much of the work I had done in PHP already followed some of the Rails patterns, but now I had a full-fledged object-oriented language at my disposal again. I thought I had finally found the best of both worlds — a thriving community, lots of support for graphics formats, easy database connectivity, and a nice clean dynamic language.

These days, that would sound like the end of the story. But it’s not. The truth is, I’m disappointed with Ruby. Rails is “classic web development done very cleanly”, as Ramon Leon says. And Ruby is my favorite non-Smalltalk language. But it’s not Smalltalk. In fact, I’ve come to see that Ruby missed the mark on several points.

  1. File-based source control. In a Smalltalk image, all of the classes and code libraries your application needs are available to you immediately. Tools like the Refactoring Browser are much harder, if not impossible, in Ruby.
  2. Reflection. Ruby’s reflection is OK, but it’s much weaker than the reflection in Smalltalk. If more of the Ruby base code was itself written in Ruby, and Ruby allowed better reflection, a Ruby code browser would undoubtedly be easier to write (and more powerful once written).
  3. Speed. The Ruby interpreter is slow. In Rails, I still end up writing more complicated database queries than I should have to, because the Ruby interpreter is so slow to process data in memory.
  4. No Keyword Messages: Travis and I ran some tests using keyword-style messaging using Ruby’s last-argument-collapsed-as-hash, and the performance was terrible.
  5. Blocks. Ruby simply missed the mark on on these. All blocks should be first-class objects, not just a layer of syntax.
  6. Live Interaction. Irb is good, but Smalltalk workspaces are much better.
  7. Debugger. The Ruby debugger feels like gdb compared to Smalltalk. Most of the time, people opt to debug using console output and interactive exploration using Irb. It’s better than printf, but not much.
  8. Class Library: The Ruby class library is much younger than the extensive class library in Squeak or VisualWorks.

As far as Rails is concerned, I have far fewer criticisms. But once you’ve looked at Seaside, and you really understand the approach Seaside is taking, Rails just looks old. I never want to marshal data through a URL again if I can help it.

I’ve also come to see that unless you’re a light user of a technology, you have to be able to support yourself. This is not a downside for Smalltalk, it’s a reality of the complex environment we work in. Smalltalk’s web and graphics tools have come a long way lately, but ultimately Smalltalk empowers you to support yourself in a way that Ruby just doesn’t. I have been digging in the Ruby 1.8 source tree more often than most, and it’s not nearly as easy to navigate as the Smalltalk base. Remember, most of the Smalltalk base is implemented in Smalltalk.

Seaside is certainly more advanced than Rails in terms of raw technology, to the point that it’s hard to wrap your head around the concepts. It took me two attempts, and I’m fairly young and intimately familiar with Smalltalk. Rails is smoother — it gives a better out-of-the-box experience in the short term. But for larger web apps, you need to be thinking further than that.

Don’t be surprised if Seaside just looks weird to you at first. Leave it for a little while and then come back. You’ll be glad you did. And when it clicks for you, beware. You won’t ever look back.

13 Comments

Filed under Rails, Ruby, Seaside, Smalltalk