Saturday, October 13, 2007

Extending Rails

Rails is the silver bullet. It's not perfect, but it strives to be and does nearly every thing you'll need. Of course, the context is that you are building a web application with a small team of 5 or less and that 2 of you rarely work in the same area at the same time. Oh, and you don't mind a test suite that takes a few minutes to run, but that isn't a big deal because you TDD now and then, but you mostly test after anyway. And, most importantly, you have the authority to say "no" to features that turn out to be a bit too complicated to implement.

Fortunately, a lot of Rails applications are built in environments similar to the one above. Unfortunately, the impact of Rails will be limited as long as it only provides solutions for those environments.

I'm not one for reinventing the wheel, that's not what this post is about. This post is about using Rails in unintended ways and how to adapt the framework to make it more productive in those environments as well.

I like web apps and small teams, but I do have a different view on testing. I like testing, it makes my job easier. I prefer TDD, and I run the tests very, very often. Since my work style utilizes the test suite, I need it to run quickly. My style differs from many Ruby/Rails developers and I think that's okay. The standard Rails testing is significantly better than nothing and I think it's great for everyone who's happy using it. If you aren't happy with it, I might have a few ideas for you. What I find interesting is the violent reactions that appear when anyone suggests a solution that doesn't follow traditional Rails suggestions.

Obie recently quoted Zed.
If DHH ain't doing it, you don't fucking do it. (Seems every time some clever fellow gets into trouble it's because of that.) -- Zed Shaw
Obie's post was a funny read, but there is almost always truth in jest. The "one true way" sentiment of the Rails community doesn't make sense to me.

I'm not sure how the community adopted the attitude. Rails clearly encourages you to extend it to your needs. The entire plugin system was designed to help you extend Rails. In fact, the plugin system has helped evolve Rails in many ways. Sexy Migrations began as a plugin announced on Err the Blog. Simply RESTful led the way for the Rails REST revolution. Despite the success stories of some plugins, many Ruby/Rails developers are very averse to extending Rails in anyway. Personally, I find this attitude disappointing and destructive. The next great feature to Rails core could come from any one. However, the "one true way" attitude may cause an unsure developer to remain quiet about their ideas, thus stifling innovation.

All applications are not created equally. Some are large and complex, others small and simple. Rails can be used to deliver in both environments; however, it's the customizations that can be the difference between delivering on time or far ahead of schedule. Rails is the foundation, but it's your responsibility to build on that foundation in the way that provides the most value. Sometimes that means adding your own patterns to help deliver for your specific domain. That's okay, in fact, sticking to vanilla rails at the price of productivity isn't a decision that I expect any good developer to make. There's a reason that David and Jamis introduced the presenter pattern into Highrise. They are good developers looking for each opportunity to improve their tools. Ultimately, David didn't like how the pattern worked for him; however, Marcel Molina Jr has a new presenter implementation that looks very promising. That version may make Rails core, or not, but that isn't the point. The point is that the Rails core team doesn't stick to vanilla Rails, and (provided you have a need) neither should you.


  1. Anonymous8:15 AM

    Very true. I saw Marcel's lightning talk at RailsConf in Berlin about his Presenter ideas. It looked promising and he seemed to attack the problem from a slightly different angle from the conventional Presenter. Unfortunately it seems he has no plans to open source it, unless you know any different?

    At SonicIQ, we have a number of plugins which help bend Rails to our way of working. I spoke to you briefly after your Presenter talk about a Presenter plugin we are working on, this is working out great for us however as you mention, what's a perfect fit for one person may not be for the next.

    I would be interested in getting you feedback on our Presenter plugin once we have completed the remaining code (the remaining parts are only in tests currently). The whole implementation is based around a primary model with "presentables" that pivot off that model. Also we use Decorators that add helper, partial, widget etc. accessors to the vanilla columns (for use in views).

  2. Man, I went plugin crazy on a Rails project I did for class in my last semester.

    If I can get the momentum back to start working on my own pet project again, I'm gonna go plugin crazy there too.

  3. Amen. There are a baffling number inconsistencies in The Rails Way of thinking, but they really all do boil down to "If DHH ain't doing it, you ain't fucking doing it."

    Oddly, unless it's coming from DHH or another core member, the One True Way of Rails is that there IS no one true way. If core does something, that's the way to do it, but God help you if you try to promote a plugin as the Right Way; you'll see five other plugins reinvent the wheel. Eventually, one of those plugins may make it to core, and when that happens, it's the True Way. Sometimes, the reverse happens - core stops needing it, they extract it, and it's no longer supported or even updateable - I believe the acts_as plugins are now extracted but "deprecated", and anyone who wants to improve them has to go make a new one and get mindshare from scratch.

    Cache consistency, default security, concurrency, none of these things matter to Rails, because they don't matter to DHH. If you want to do them yourself, great, make a plugin, but "they don't belong in core". Even a recent proposal to make Rails emit valid HTML by default failed, because HTML doesn't matter anymore.

    Yet there is equal resistance to making the plugin engine more powerful. It's elegant in its simplicity, but that simplicity means that there are things you simply can't do from plugins - like require other plugins. Which causes great pain when they're also extracting things that "DHH ain't doing" anymore into plugins.

    Luckily, it looks like the core team is finally becoming more amenable to the idea of more powerful plugins, but it's been a long time coming. I've been watching the Engines debates for years, and nearly every important feature of engines went from "you shouldn't do that" to "Rails doesn't need that in core" to a core feature.

    I guess DHH is doing more things now.

  4. Anonymous12:50 PM

    I blogged about (over a year ago) and still maintain that there is an action missing in the standard 7 that make up the CRUD/REST setup, but would anyone listen (despite the benefits)? ...No!

    This to me is a huge flaw, especially for those without javascript, or if some additional data needs to be logged before destroying a record, e.g. reason for deletion.

    P.S. Sorry about posting twice, I must get out of that habit.

  5. "I believe the acts_as plugins are now extracted but "deprecated", and anyone who wants to improve them has to go make a new one and get mindshare from scratch."

    Maybe you should _believe_ less and _know_ more...

  6. The majority of developers in most areas are only interested in using what's put before them - the idea of applying any creativity and sharing the results simply doesn't occur to them. Worse, a subset of that majority are the kind of shrill naysayers who actively discourage any modification, extension or improvement to their tools.

    It's not Rails, it's people.

  7. This is a good post.

    Anyone who blindly follows DHH without any consideration for the requirements of their own application is acting irresponsibly and unprofessionally. The community needs to appreciate creativity and encourage new ideas and stop appealing to the authority of the core team.
    As you said Jay, not all applications are created equally and it is not reasonable to expect that the core team should know what works for each individual application, they understand neither the requirements or the constraints; that is the job of the developer.

  8. "Maybe you should _believe_ less and _know_ more..."

    In my best Peter Falk: Yesh. You're very shmart.

    More precisely: The last decision I heard on rails-core was that the acts_as plugins would be deprecated and not open to improvements.

    Quoting Koz from rails-core:

    "I think the best bet is for the 'will_paginate' style approach. We'll keep a plugin in the rails repository which has the existing functionality, and take patches to fix any glaring bugs. However new and exciting developments can happen elsewhere...I don't see any reason to have an 'official' successor until they've proven themselves with a large and happy user base. Market forces and all that..."

    If this was not in fact the final decision then I'm very, very happy (modulo my sadness at things being decided but not discussed on rails-core). You seem to know something about this, so perhaps you should _hint_ less and _post_ more!

  9. Anonymous2:11 AM

    By default, you should follow the tool's mindset. This happens in any well-designed environment (Apple's Cocoa comes to mind).

    Of course, with time passing things should improve i.e. change, but changes must be carefully considered using the holistic view. Otherwise you get Windows/PHP/Java/C++ bloatware - lots of inconsistent features that are a nightmare to use.

    Steve Jobs once said that the hardest task of any was saying NO.

    Keeping product well-designed (consistent,easy-to-use,...) is very hard and I am happy that core team is still doing it despite the frequent criticism.

    Well-designed also means that Rails is not everything to everybody. And this is fine, also. If your requirements are so different, use some other tool or create Rails fork for your private use.

    But think twice before forking. Just a single look at PHP or Java or MSWindows or C++ should remind you what can happen when people stop caring about design and start adding things left and right. You wouldn't want your software to be compared to those, would you?

    On the other hand, if that comparison doesn't bother you, don't think too much and just do it :-)


Note: Only a member of this blog may post a comment.