Ruby on Rails Revisted

After much frustration and time setting up a reasonable Java development environment, I decided to give Ruby on Rails another chance. I’m glad I did. In a quarter of the time it took me to get Tomcat not-quite working with a remote build script, I was able to get an actual website up and running with the first part.

And all it took was feeling dirty the whole time I did it.

See, my problem with Ruby (which is exacerbated with Rails) is that you can’t write really good code. You can write code very productively, but there’s a lot of hand-waving and very little enforcement of actual business model rules. Everything’s mutable (even class definitions), and that instability scares the crap out of me. The fact that some stuff just “magically works” isn’t much better. And it grates on me to relegate my database down to an optimistically locked object store.

But, assuming you’re willing to accept that kind of hand-waving “Seems to work” (which I used to), it’s a really nice framework for development. And it certainly got me up and running a whole Hell of a lot faster than Java/Tomcat.

And the fact that I run it all at my web host (which won’t run a Servlet app server for some reason) makes it all that much nicer. I love not having to think about infrastructure.

Related posts:

  1. Ruby on Rails: Fixtures Gotcha
  2. Ruby on Rails: One Thumb Up, One Thumb Down
This entry was posted in To Be Categorized and tagged . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.
  • dave

    My issue with Ruby on Rails is that it doesn’t allow database-level enforcement of referential integrity, and all those other nice things databases can do for you. I think it’s WONDERFUL for people who aren’t serious database programmers, or people who aren’t terribly concerned about the growth of their data model. The shift from configuration to policy is a marvelous idea. But it needs to ALLOW a more sophisticated approach to data modeling!

  • http://enfranchisedmind.com/blog Candide

    That’s probably the biggest issue I have: by making the DDL the source of truth, they drastically limited the capabilities of a database. Compared to Hibernate, it’s a PITA in Rails to generate non-DDL-based data members (like stored proc-based properties), and it is wildly heavy.

    My second favorite anti-Rails issue is the fact that read-only properties and derived properties call all kinds of headaches. As someone who is a BIG fan of immutable data objects, the ability to arbitrarily set any given data value gives me conniptions.

    My final issue is the fact that I’m yet to successfully be able to implement transformations on data to and from a data server. When creating a new username/password combo, I’d like to use the DB’s hashing capabilities to hash it. When inserting data into a particular blob, I’d like to use the DB’s gzip capabilities to compress it. I suppose I could define those as triggers, but I’d much prefer to wrap it into my application code so that it’s obvious to coders what’s going on. In the latter case, it’s also much more efficient to gzip it on insert rather than doing the insert, then doing an update to gzip it.

    My other issues are that it’s 1) painfully heavyweight and 2) extremely difficult to do genuine test-driven development, because changes have non-obvious impacts, and there’s no compile time checking (there being no real “compile time”). I care more about #2 than #1 now that I’ve moved onto more powerful infrastructure, but they both make me cranky.

  • azcoder

    Let referential integrity be handled along with the rest of the validation in the business tier. Focus on building a rich domain model. Handle all of the relationships in the model.

    The time of heavy coding in the database is ending. Oviously, complex relationships and validation are better handled by a rich language – not SQL or DDL.

    It seems as if you WANT to use the db to do many things. I think you should really question WHY you want to do this. Is it because you are familiar with it, or because it is a superior approach. I tend to think it is the former.

    Finally, the lack of compile time checking is a blessing not a curse. Embrace it. It increases productivity.

  • http://enfranchisedmind.com/blog Candide

    I really like compile-time checking. Or, to be more precise, I like to let the computer do as much bughunting as possible. By not having any kind of automated checks, you’re just asking for bugs to sneak into places that only are exposed months down the road, and by surprise values sneaking into the output far down the road. And the ability to re-write the class makes unit testing somewhat difficult.

    And I do want the DB to do a lot. Namely, I want it to be responsible for managing how things are stored — that’s beyond the scope of the application itself. It’s not a part of the model that I’m storing this stuff in that way, or to ensure data integrity across many different applications. A DB is better-optimized to handle data manipulation than Ruby (SHA1 and GZIP in Ruby are dogs), and DBs allow you to define data in such a way that it can be shared across applications and languages.

    I think you’re drastically underestimating the power and utility of databases. The DB isn’t just a persistant object store, it’s a ridiculously hyper-tuned way to define and store data throughout an enterprise.

  • bhurt-aw

    Finally, the lack of compile time checking is a blessing not a curse. Embrace it. It increases productivity.

    My advice: learn Ocaml. Learn Haskell. Learn SML. Learn F#. Learn a language with a real type system. And no, Java/C++/Pascal don’t count. Strong static type checking vastly enhances productivity. You have the flexibility to do what you need to do, and it finds your bugs for you.

    Now, on to the meat of the comment, as this came up at work. There are two problems with implementing certain kinds of logic in the programming language and not in the database. The first is performance. The more filtering you can do at the database level, the faster the program will be- if for no other reason than you won’t have to schlep all that data across the network. If your database is megabytes, this may not be that big of a problem, but if your database is terabytes, this is a problem.

    The second problem is slightly more subtle- implementing especially consistency checks in the app code and not in the database runs into many problems. First, and most importantly, it ties you to one one language. Or at most a small set of languages that shared a run time and can share libraries. So, for instance, you might be able to use both Java and Jython, for instance, or VB/C#/C++.NET. But if you implement the consistency checking in, say, Java, and then want to access the database from, say, Ruby, you have to implement (correctly!) the same consistency checks in both languages. And keep the consistency checks in sync as (inevitably) they change!

    Note that this is where you get single-language shops going. Because adding a new language isn’t just about writting code in the new language, it’s about porting large hunks of the business model in the new language. The next time you say “we should use Ruby” and the response is “we’re a Java shop”, remember this reply- this is probably what they really mean.

    If you implement at least the consistency checks at the database level, the problem goes away. Stuff that needs to be shared between the different languages, should be shared at the point of sharing- the database. Of course, this immediately does imply at least a two language shop- the app level language and SQL. Going from two languages to three is a much smaller leap than going from one language to two.

    To answer the next question: “what’s wrong with just writing everything in Ruby?” the answer is that, sooner or later, Ruby will be replaced. Just in my professional lifetime, I’ve seen things switch from C to C++, from C++ to Java, and now from Java to Ruby. And I’m not a greybeard. Sooner or later a new language will come along to replace Ruby- it has for every other language so far. At which point being able to support that second language is a huge advantage.

  • http://enfranchisedmind.com/blog Candide

    What’s even nicer is when you can implement your model in an application-level language, but in the database itself (like Postgres can). Have your cake at eat it, too!

  • Joe

    “The time of heavy coding in the database is ending.”

    Spoken like a true PHPer. That’s what turned me off about rails, DHH clearly never recovered from his PHPitis and it infected rails. From the “databases are just dumb storage” calamity to the lets_make_dozens_of_unwieldy_functions_that_you_cant_remember_with_names_like_this style of design, to the misguided notion that writing code faster is of paramount importance, but writing correct code and being able to read it later doesn’t matter at all. Everything about it just makes me ill. That and his horrible attitude about security was very scary for someone writing a web framework.

  • http://enfranchisedmind.com/blog Candide

    Joe –

    I had been biting my tongue about it because I thought I was just being stupid/inexperienced/whatever, but THANK YOU!

    I hate hate hate hate hate hate hate the fact that Rails has far too many methods that have really poorly documented interconnections and interdependencies. And I always typo on the stupid method names, but no compile-time checking means I don’t notice until there’s some nil object where there shouldn’t be one…

    BLARGH!

  • Categories