each-require anti-pattern

This is going to be a little rant. This little anti-pattern I see all over in Ruby code by various people:

%w{yaml fileutils}.each { |lib| require lib }

I cannot understand why do people write it like this. This is neither shorter nor easier to read than the ‘normal’ version:

require 'yaml' 
require 'fileutils'

So, why is that? There must be some good reason to write like that, because I don’t believe that experienced Ruby developers would do it only to make their code look more ‘hackish’.

Some reasons that I see:

  • you don’t have to write the quotes,
  • it’s easier to add more libraries,
  • it’s shorter when you require 4 libraries or more,
  • it’s one line,

are questionable and don’t justify, in my not so humble opinion, using the horrible syntax. And, if you use it again and again, why not turn it into some more acceptable form. It’s Ruby, remember? We can redefine require to make it accept a list of libraries to load instead of one. Then we could write:

require 'yaml', 'fileutils'

or even:

require %w(yaml fileutils)

if you really, really can’t stand four quotes and a comma.

So, is it difficult to redefine require like that? Not really:

module Kernel 
  alias_method :require1, :require 
  def require *args 
    args.collect {|lib| require1 lib} 
  end 
end                        

require 'yaml', 'fileutils'                        

p FileUtils::pwd 
p YAML::dump(true)

As we can see, it only took 6 lines of code (which could be compressed to 3) to redefine require so that it accepts any number of parameters. I used collect instead of each, because Ruby’s require returns true for success and false for failure, and someone might want to examine the results of require‘ing. Typically, if all went OK, a list of true objects will be returned.

So, insert this snippet into your application and stop using the eachrequire anti-pattern!


3 responses to “each-require anti-pattern

  • Logan Capaldo

    False is not failure. False just means the lib has already been required. If require fails an exception will be raised (usually LoadError).

  • Samuel Tardieu

    I would rather return a dictionary so that you can know what library could not be loaded without duplicating the list given to ‘require’.

  • szeryf

    Samuel: I agree that this would be easier to check, but the return value is ignored in 99% of uses so I doubt it’s worth implementing it. Also, as Logan said, this indicates that lib was already loaded rather than problems.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: