ActiveSupport Considered Harmful

This an open letter to my fellow ruby gem authors and maintainers.

Hi Everybody,

It’s been a while. You’re doing awesome stuff; all this great code out there making Ruby do all sorts of nifty things. It’s a big reason – maybe the reason – why being a Rubyist is so great. But yeah, there’s just one thing that’s been bugging me… we need to talk about ActiveSupport.

ActiveSupport is great, don’t get me wrong. I love try and tap and sum as much as the next guy. It sure saves me some lines of code. But the problem is it’s, well, a little invasive. Many of us love Ruby precisely because it’s more flexible than a Russian gymnast. But just because you can reopen Object and add

class Object
  def your_great_method
    puts "HEY I'M CHANGING OBJECT"
  end
end

doesn’t mean you always should. As we all know, ActiveSupport is one giant ball of I’M CHANGING OBJECT (and Enumerable and Array and String and, well, you get the picture). This is a pretty awesome idea in a controlled environment like Rails. Rails is all-encompassing. When you write Rails, you’re not really in Ruby anymore, you’re 3 layers deep, Inception style, inside DHH’s dream of web programming. In that world, Object can do magic things and Strings can inflect right back on themselves. And so, of course, ActiveSupport is an integral part of Rails (more on that in a moment).

The problem comes when you decide you just can’t  live without tap or a few of these other modern conveniences and so you throw in the ol’ ActiveSupport dependency in the gemspec. The first effect of this is that whatever project your users are working on now much bring in this giant ball o’ Ruby changin’ with its various invasions, idiosyncrasies and occasional incompatibilities.

But, you say, most people are using Ruby for Rails and Rails has ActiveSupport baked right in. We’re good right? Well, no, actually. This is where it gets really painful. When you’re gemspecin’ and you decide to throw in that latest version of ActiveSupport, well, you’re basically telling every Rails user out there that’s not on the latest version that they need to upgrade their entire environment just to use your gem. Now, the Ruby community is made up of people who are pretty early adopters so many people are on the latest and won’t even notice. However, as Ruby gets more mature and lots of people have lots of versions of things out there, not everyone can just upgrade at the drop of a hat. You’re cutting off those people from your gem awesomeness unless they either a) upgrade (which isn’t always immediately possible) or b) resort to horrifying monkey patches. And all this because you just love sum so much.

So, my fellow gem authors, I ask you to think twice next time you really want to use that convenience method that’s only in ActiveSupport N.N.N. Perhaps a little helper method would do? Maybe one that’s in your gem’s own namespace perhaps? Your users will thank you.

Sincerely,

Hayes

12 comments

  1. What Ruby needs is scoped namespaces, letting these extensions only exist for the moudules that are calling them. AFAIK there is already serious interest in this from the Ruby language team, and they are working out how this could happen.

  2. @saurik You’re absolutely correct. Scoped changes would be amazing, and solve this problem. They’re also on the Ruby team’s plate for Ruby 2.0 :)

    @hayes have you been following the work we’re doing in AS 3.0 to make it easier to pick and choose just the parts that you want? For instance, you should be able to use the inflector without changing any objects, and without requiring any other bits of ActiveSupport.

  3. “When you’re gemspecin’ and you decide to throw in that latest version of ActiveSupport, well, you’re basically telling every Rails user out there that’s not on the latest version that they need to upgrade their entire environment just to use your gem.”

    I present to you bundler and rvm. Welcome to 2010.

  4. Rails 3 is making a huge effort in modularizing ActiveSupport so you only have to include the specifc modules you want. But yea, I agree.

  5. @saurik @yehuda Re: scoped namespaces. I wasn’t aware of that. Sounds interesting but like it’s still early days yet. I’ll read up on it.

    @yehuda @julio I’ve definitely been following the work on AS 3 and I really appreciate the drive toward modularity. I think that will help a lot.

    @paul I appreciate the sentiment and I certainly have no desire to see ruby advancement held back by too many legacy concerns but my point here is that if you’re writing a gem, don’t force anything on your users unless it’s absolutely necessary. In most cases, something like ActiveSupport is more about convenience than necessity.

  6. If you’re just using 1-2 methods in activesupport, one shouldn’t be including the entire library into one’s gem.

    e.g. If someone wanted the convenience of blank? you should just write it yourself instead of including full libraries into your gem.

    As Yehuda stated, AS3’s modularity solves much of the reasons why people include all of active support, however, if it is for 1-2 methods, it’s probably better to just write it yourself instead of adding more dependencies.

  7. Someone should get ActiveMerchant to stop requiring it. Major nightmare.

  8. The beauty of the MIT License is that it’s perfectly legal and ethical to reuse other people’s code if you give proper attribution. So if you really need only a method or two from ActiveSupport, just copy it and give credit its authors.

  9. Couldn’t agree more!

  10. Completely agree.

    Working with rightaws, and the appoxy fork of it, outside of rails has proven to be very problematic due to reliance on multiple activesupport methods added to String. I consistently find my self defining things in the local namespace to eliminiate the dependencies.

    Along the same lines, I’ve also noticed multiple methods in activesupport that have been brought back into either ruby 1.9 or ruby1.8.7, where the activesupport dependency is only needed when using 1.8.6 or below.

  11. Couldn’t agree more.

    In general (but in particular as a non-rails ruby user), I am really reluctant to introduce any gems with ActiveSupport dependencies just because of the sheer volume of stuff which ActiveSupport adds. More modularity may help with that, but at the time of recent versions of ActiveSupport don’t seem to provide any way to avoid loading activesupport/json – which as noted clashes nastily with any native (JRuby or C extension) json library you have loaded. This is a very real problem for us and has stopped us using some pretty basic and important gems like ‘mail’.

    If you’re writing a library for wide re-use, please don’t be selfish – keep your dependencies to a minimum, and don’t introduce any dependencies which clash with other libraries in common use.

  12. One word: gemsets. RVM gemsets help massively when trying to avoid needing the latest version of a gem for a dependency, whilst another rails project needs an older version. That, and AS 3 should improve the situation greatly.

    On the other hand, I agree completely. It’s tough sometimes to balance the niceties and recreating the wheel. Generally, I would err on the side avoiding AS as a gem dependency if possible. Unless, of course, you’re building a gem with the intent of using it with Rails.

Leave a Reply

Your email address will not be published. Required fields are marked *