Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Why "require 'rubygems'" Is Wrong (tomayko.com)
41 points by blasdel on Sept 2, 2009 | hide | past | favorite | 52 comments


Context failure: linking to Ryan Tomayko's article without linking to the article that's brought it to people's attention again, namely Josh Peek's 'Gem Packaging: Best Practices'.

http://weblog.rubyonrails.org/2009/9/1/gem-packaging-best-pr...

Giles Bowkett has also written about the related issue of screwing up the load path:

http://gilesbowkett.blogspot.com/2009/04/unshiftfiledirnamef...

It's also worth noting that Ruby 1.9 requires rubygems automatically, as it's included in the standard library.


Thanks! Both the Rubygems Bundler and Rip (as Josh explains) are great examples of why "require 'rubygems'" might not always be the best idea.

Bundler: http://github.com/wycats/bundler

Rip: http://hellorip.com/


Please don't start your shell scripts with #!/bin/sh. If a script foobar needs to be interpreted with sh, just run it with '/bin/sh foobar', instead of ./foobar.

Please don't put #include <stdlib.h> in your C source files. By doing this you remove my ability to compile your files in an environment where the standard library is not present. Instead, whenever you need to compile a file that uses stdlib.h functionality, simply use a small wrapper file that includes stdlib.h and then includes your source file, and compile that.


Analogy failures:

* Configuring /bin/sh to point to my shell of choice is trivial (and common)

* Overriding the shebang is even more trivial, if I don't like sh, I can call `./mysupershell foobar`

Meanwhile, if I don't want gems on my machine and manage my $LOAD_PATH manually or through other means (which seems to be Ryan's case) but you decided that your library was going to require rubygems dammit, I have the choices between

* Installing rubygems (and duplicating my $LOAD_PATH handling efforts) anyway because you decided I was to have rubygems on my machine whether or not I liked it

* Adding an empty rubygems.rb to my $LOAD_PATH (yeah, kludge)

* Hacking Kernel#require to ignore gems request (yeah, horrible hack)


If you're going to be in the tiny tiny minority of Ruby devs that insists on not installing rubygems, having a stubbed "rubygems.rb" in your load path is not an unreasonable request --- particularly compared to the request that everybody else uses some contorted command line to execute their script to accomodate you.


It's unreasonable if you want to have both rubygems and some other package system available at the same time, as is most often the case. Having to use the contorted command line is the rare case, as you almost always invoke ruby scripts through the rubygems generated wrapper or some other isolated script intended specifically for command line use, which takes care of rubygems itself.


Well, seriously, don't start your scripts with #!/bin/bash if you don't require any of bash's extra scripting functionality. (If you have to ask, you don't.) Bash isn't standard, sh is. It makes porting things other Unixes (e.g. the BSDs) easier. Not every Unix is Linux.


Incidentally, I've seen some people argue it's more portable to use '#!/usr/bin/env sh' than '#!/bin/sh'.

Most every machine I've been on has both /bin/sh and /usr/bin/env, so it's a bit of a non-issue: but does anyone know what the 'correct' shebang for a sh script is?


The latter, because it simplifies using alternate sh if you need to e.g. create separate execution environments, à la virtualenv in python.

In fact that's a good example, though it's in python: if you use `#!/usr/bin/python` as your shebang your script will break under virtualenv, whereas if you use `#!/usr/bin/env python` it will work perfectly.

Now /bin/sh is probably a POSIX requirement so it'll always be there and you can always override the shebang with an explicit shell call (or by temporarily rebinding /bin/sh though that one requires root access), but going through env doesn't cost you (as a programmer) more and it simplifies the job of the users (if they need to sandbox your script in some way)


Thanks, that makes sense. I suppose I'll use an env shebang from now.


Tcl taught me to "env tclsh" instead of specifying the path, and I do it religously now. You don't want to hardcode the path to the interpreter; people will often install their own, and no matter what the vendor says, Tcl, Python, and Ruby aren't really part of the base system.


It's very difficult to setup a gentoo box without python installed. (maybe impossible?)


More portable in that you do not hardcode the path. Ruby, Python, and similar are generally not in the same location across systems.

Unfortunately on Ubuntu (and probably other Linux variants) you can’t pass arguments to the interpreter, e.g. the following gives an error on Ubuntu (works on OpenSolaris, FreeBSD, and OS X):

    #!/usr/bin/env ruby -wKU
    puts "æblegrød"


I use /usr/bin/env for most things (Python and Lua, for example), but still use /bin/sh for the bourne shell, because that's part of the standard.


"Please don't start your shell scripts with #!/bin/sh...run it with '/bin/sh foobar', instead of ./foobar."

Are you serious?


He's making an analogy to the article.


Yeah but his analogy is wrong in that /bin/sh is usually a link (or a copy) of the user's shell. So the user can easily configure which shell is loaded and how using /bin/sh (though /usr/bin/env sh would probably be even better).

What Ryan's gripping against here is that the people requiring rubygems usually don't care for rubygems itself. They just want to require a library which (on their machine) happens to be managed via rubygems.

And this management is not the sole strategy. Somebody else could be using another utility, or even no utility at all if they handle their $LOAD_PATH manually (which Ryan apparently does).

And in these cases, requiring rubygems breaks their platform: they might not want or care for rubygems. In any case, it's usually not needed so why require it?

And that's Ryan's point: by requiring rubygems when it's not needed (which is most of the time) in your library, you're forcing people to use rubygems whether they like (or need) it or not.

Furthremore, his analogy is also wrong because even with a /bin/sh shebang *it's trivial for me to overload it by calling `./mysupershell yourscript`. With `require rubygems` there's no such recourse (apart from `require` hackery or other such crap).


The /bin/sh link thing is a Linuxism --- in fact, I think it's a Debianism. On FreeBSD, Solaris, and OS X, /bin/sh is either always Bourne or always Bourne-Again.

Also, the link that is there is always to a Bourne shell variant. It's not like your system will run fine with ksh as /bin/sh.


Actually your system should work just fine with ksh as /bin/sh. KornShell is a superset of the Bourne shell.

http://www.kornshell.com/doc/faq.html


OK ksh a bad example.


That's what I was hoping...I guess I prefer my sarcasm a little more heavy handed. lol


The system you use to manage your $LOAD_PATH is not my library / app / tests concern. Whether rubygems is used or not is an environment issue. My library or app should have no say in the matter. Explicitly requiring me to not use rubygems is either not necessary or misguided.

When you feel the urge to strike "require 'rubygems'" because some shit isn’t working, stop and consider whether one of these solutions is more appropriate:

1) An empty rubygems.rb in your $LOAD_PATH should do the trick.

2) Redefine Kernel#require to intercept calls to load rubygems and silently discard them.

Why You Shouldn't Force Non-Rubygems On People

When I write you a library, appplication, or tests, I may not want to have to care how you execute my program. When you require that I not include 'rubygems' in my code, you remove my ability to make that decision. I cannot anticipate all of your requirements in advance, but you can set up your environment properly such that the defaults I choose are overridden.


So instead of separating the library and the environment you suggest that ugly hacks are more appropriate? Really?


Having the 99.9% of ruby users who don't have a religious problem with rubygems all specify rubygems on the commandline seems like a more ugly hack than having the 3 developers in the world who care about this problem alter their environment.


You underestimate the amount of discontent with rubygems. There is at least one replacement available (hellorip.com) and for good reason. I've already come across a few libs that use it exclusively.

Ruby 1.9 actually ignores "require 'rubygems'" entirely which I suppose will make this whole issue moot, as soon as we all start using it.. um, any day now.


The point about not requiring rubygems in a library or a gem (as ironic as that may sound) is that by doing so you're coupling your implementation to your environment. This is as bad as coupling your classes to global constants, and not something you should do. Case in point: Rails allows you to "unpack" gems to make your app more portable, and it shouldn't matter if the "foo" gem uses the unpacked version or the one installed in the gem repository on the server.


Let me see...every time I have required rubygems it has done exactly what I intended for it to do (which is to allow me to load some ruby gem), so I think I'll just go ahead and ignore your advise.


Stupid article.

So if I write a ruby program that needs rubygems I need to ask people that will run it to please run my program with "ruby -rubygems foo.rb" or set an environment variable, instead of just requiring the gems. Because that would infringe on the domain system administrator of that system. That doesn't make much sense to me.


> So if I write a ruby program that needs rubygems

I think Ryan's point is that most of the time your program doesn't require rubygems itself. You just happen to manage your libraries using gems, somebody else could do it an other way (and never need rubygems), but you're forcing that person to install gems regardless.


Things tend to break a little less over time if I can require a version of a gem, like:

gem 'png', '= 1.1'

The good part about rubygems is that it's possible to get a certain version of a gem. I'd rather use gem and version than just require "png", and get god knows what version or file.


That's a good point, and in this case requiring rubygems does make sense, but I really doubt that's the most common use case.

Stuff like this: http://github.com/mojombo/jekyll/blob/2f2e45bedf67dedb8d1dc0... or that: http://github.com/mwunsch/weary/blob/cd7b35ccee66757c5efb0a0... is probably the kind of stuff Ryan rages against in his rant (though you'd have to ask him if that's that, and how he'd see you use case)


yep I can agree that

  require 'rubygems'
  require 'png'
is kind of pointless.


I don't know who is voting you up? Maybe because you sound angry, and people associate angry technical rants with people who know what they're talking about?

"I think Ryan's point is that most of the time your program doesn't require rubygems itself."

Yeah! You could have manually downloaded the files for all the libraries you need, placed them in the directory, and required them directly. See, who needs rubygems? Oh hang on, rubygems is about 1000x easier than doing all that.

"You just happen to manage your libraries using gems"

Yes, because gems are the standard way of managing libraries in Ruby, and work transparently and conveniently. Where the hell is Ryan getting all these gem-using libraries anyway, if not from gems? And what is supposed to be wrong with it, anyway? I have never had a problem using a non-gem library even with gems present and a duplicate installed. Just require the non-gem lib first. What is so freaking hard? I assume it's some stupid problem he has to solve at Heroku - and his solution is trying to change how the entire Ruby community does things, to their detriment, benefiting only him. Screw him.

Oh well, anyway .. who cares. You're a crank and so is he. Rubygems is here to stay and if you don't like it .. well again, who cares.


> You could have manually downloaded the files for all the libraries you need

Yes, why not?

> placed them in the directory

Placed them in any directory on my $LOAD_PATH, yes indeed.

> and required them directly

Uh no, there's nothing to touch there. Library is on $LOAD_PATH, any require $the_library will find it perfectly normally.

> See, who needs rubygems?

Nobody. Rubygems is a very nice convenience, not a requirement for anything.

> Where the hell is Ryan getting all these gem-using libraries anyway, if not from gems?

Tarballs? Github? Rubyforge? His colleagues? The Internet?

And as a side note: if the library was obtained from gems, then it was loaded from gems, which means by the time the library is reached rubygems has already been required and loaded.

Where's the sense in requiring the tool which loaded you in the first place, exactly? Doesn't that seem a bit dumb to you?

> And what is supposed to be wrong with it, anyway?

And what's wrong with not wanting to use it, anyway? (and what's wrong with it is that they clutter the $LOAD_PATH. You don't care, Ryan apparently does)

> Oh well, anyway .. who cares. You're a crank and so is he. Rubygems is here to stay and if you don't like it .. well again, who cares.

You… completely missed the point. It's impressive.


Agreed. I don't understand how require 'rubygems' is any less succinct than ruby -rubygems foo.rb.


This is called begging the question:

"Why You Shouldn’t Force Rubygems On People:

When I use your library, deploy your app, or run your tests I may not want to use rubygems."


Whoever this guy is, he really needs to pull his head out of his ass.

If someone's writing a library or app.. it's up to THEM whether they want to require rubygems or not. If you don't like how they do it.. then don't use their application/library, it's simple.

Most people create code for their OWN use and THEN publish it for others to use.


> If someone's writing a library or app.. it's up to THEM whether they want to require rubygems or not.

But… why? Most of the time it's not like they actually need gems. They just happen to use gems as a $LOAD_PATH manager, so they're leaking their environment configuration into the library. How can anyone defend that?

It's like hardcoding the paths of dynamic libraries, or respawning your shell scripts because damn it if any god damn user is going to run it with anything other than /bin/bash.

It's completely insane.


they just happen to use gems as a $LOAD_PATH manager

Oh come on. That's like saying "you should not make your MacOSX app require Finder just because some people just happen to use it as their file manager". Just happen? It's the default, and overwhelmingly dominant, choice! It's freaking bundled in 1.9 core!

rtomayko is a prominent and well regarded community member but he's pretty much a crank on this issue. He is the extreme odd one out who doesn't like rubygems, so it's on him to deal with it, rather than causing inconvenience for everyone else. He doesn't even give a good, or any, reason why he doesn't use gems. And as if I'm going to write -rubygems every time I run anything, give me a break.

Rubygems is the official package manager and is used without any issue by 99.9% of Rubyists. It's not 100% perfect but in general works beautifully and greatly contributes to making everything in Ruby "just work". There is no reason for people to stop using it as the default choice.


I'm also a crank.

So is Rails core member Yehuda Katz.

So is Rails core member Josh Peek.

So is Rails core member Jeremy Kemper.

Calling Ryan "the extreme odd one out" is a) untrue and b) unfair.


Right. Now I am really confused. You went out of your way to build gem building support into GH. You run a fricking gem repository, probably the largest after Rubyforge itself. If you honestly agree that using Rubygems is "utterly insane" then .. wtf are you doing?

And Rails uses Rubygems. Of course. Its ease of use is one of the reasons Rails, and indeed Ruby itself, is so popular. Is it "utterly insane" for Rails to use Rubygems, too? And if all the core members are so against it, why does it? Why is Rails even in the gem repositories?

What am I missing here? Seriously, I just don't get it.

I'm currently kinda mentoring a friend of mine who's just getting started programming (my 3rd student!). I can personally attest that Rubygems is an invaluable resource for the beginner and intermediate Rubyist. Have you considered the possibility that your ultra-expert status has blinded you to the needs of the lesser 99% of programmers?


No one has suggested, is suggesting, or will suggest that you stop using Rubygems. That is not what this is about in any sense of the phrase. Everyone loves Rubygems, including Ryan Tomayko.

This is about the best way to use Rubygems. Check out Josh Peek's recent article: http://weblog.rubyonrails.org/2009/9/1/gem-packaging-best-pr...

There are ways to use Rubygems without putting "require 'rubygems'" in your code. Those are the correct, most portable, least painful ways of using Rubygems. Learn them and cherish them!

That is what this is about: how you are using Rubygems, not whether or not to use them.


I just read that post again. Good post, but it's talking about something different. This HN article is about Ryan's views on the matter.

Of course I agree that libraries should not require it. I often want to use libraries by themselves. But apps!? What do you suggest - manually place each gem directory, by its full system file path, into $LOAD_PATH? How on earth are you going to use a gem installed in its default location by the ubiquitous "gem install" method, if not by, at some point, requiring rubygems?

This whole kerfuffle was started by this gist: http://gist.github.com/54177. Note the title: Why "require 'rubygems'" In Your Library/App/Tests Is Wrong. I thought that was a ridiculous thing to say then and still do. In my app!? That no-one else will ever see, my personal little IRC bot or something? What, pray tell, is the difference between loading rubygems on the command line every single time you run the program, or just writing in the source because you know your app needs it?

I have no quarrel with best practise for responsible use of gems. I agree completely with what Josh Peek writes. People publishing gems to public repos should absolutely learn how to do it without stepping on anyone's shoes. But that is not what Ryan says. Ryan says this:

  You should never do this in a source file included 
  with your library, app, or tests:
  
  require 'rubygems' 
and that is extremist and indefensible and, IMO, flat out wrong.

update: I mean, let's have an example. Let's take a top-level app that depends on things. I know, thin.

Here we are: http://github.com/macournoyer/thin/blob/9f391ed7fcc7c202a32e...

He needs eventmachine. He requires rubygems and loads it. Tell me what he is doing wrong. Tell me how he should do it differently. Because I can not see what is wrong with that. And if that usage is wrong, then what is the point of even having Rubygems.

update 2: And I would like to clarify that I agree Rails should only be requiring Rubygems when it is being used at the top level, such as being launched from the binary or from the script directory, not when it is being loaded as a lib. It is always the top level app's responsibility to set up paths, etc - rails is a special case because it's both an app and a library.


> He needs eventmachine. He requires rubygems and loads it. Tell me what he is doing wrong.

He requires rubygems even though what he wants is eventmachine. What's the sense?

> Tell me how he should do it differently.

Don't require rubygems. Rubygems isn't used anywhere in the code, why require it?

> And if that usage is wrong, then what is the point of even having Rubygems.

Managing your own $LOAD_PATH on your own machine(s). That's the point of rubygems in the first place.


Oh for fuck's sake. So what do you suggest? Bundle eventmachine with thin?

"He requires rubygems even though what he wants is eventmachine. What's the sense?"

Do you know even know what rubygems is? It is used to require other libraries. Like eventmachine. That is a textbook usage.

I was regretting insulting you before, but after hearing that, I don't anymore - you're an idiot.

Hey defunkt, do you endorse masklinn's comment above too?


> Oh come on. That's like saying "you should not make your MacOSX app require Finder just because some people just happen to use it as their file manager".

Yeah it is. And indeed you shouldn't.

> Just happen? It's the default, and overwhelmingly dominant, choice! It's freaking bundled in 1.9 core!

So fucking what? (and as others have said, in 1.9 rubygems is required by default so that's a very good reason not to require it yourself ever).

> Rubygems is the official package manager and is used without any issue by 99.9% of Rubyists.

And so the rest should just take it up the ass and live with completely insane and nonsensical decisions such as randomly requiring rubygems just because?

> There is no reason for people to stop using it as the default choice.

That is not what Ryan says. Ryan doesn't care how you handle your own $LOAD_PATH. If you want to use gems, knock yourself out, that's your own business not his. Ryan just asks that you don't force others to use rubygems without any justification.


I can't understand if you are arguing against people duplicating the fact that rubygems is already loaded / is part of the core lib, or that people should respect alternative choices. I thought it was the latter.

Yeah it is. And indeed you shouldn't.

You're nuts, did you know?

completely insane and nonsensical decisions such as randomly requiring rubygems just because

Just because .. it's loading required libraries? Like it is designed for? Like everyone uses it for?

And so the rest should just take it up the ass

Well .. yeah, sorry. The weird personal tastes of two people basically don't matter compared to the great benefits enjoyed by the rest of the community. So, OK.

I guess you're just never going to update to 1.9 then? So sad. Anyway, no sense arguing so whatever, carry on.


> You're nuts, did you know?

Thanks for teaching me that I shouldn't use an alternate explorer to the finder.

> Just because .. it's loading required libraries?

No it's not. It's managing your $LOAD_PATH. You don't need gems to load libraries, unless those were installed by gems in the first place if we stretch the meaning of "load libraries" a lot.

> The weird personal tastes of two people basically don't matter compared to the great benefits enjoyed by the rest of the community.

What's the relation there? What's the "great benefits" to you adding "require 'rubygems'" like so many droppings to all your libraries? It's not like anyone is arguing against using Rubygems. If you like gems, go ahead and use it. All that's asked is that you don't force others to do so.

> I guess you're just never going to update to 1.9 then?

I fail to see the relevance. Ruby 1.9 isn't going to shoot me if I don't use gems to manage $LOAD_PATH. And as far as Ruby 1.9 is concerned, since it requires rubygems on its own there's no reason whatsoever for library writers to do it themselves.


What's the "great benefits" to you adding "require 'rubygems'" like so many droppings to all your libraries?

Not that it makes any sense arguing further, but for the record, I was not talking about libraries, I was talking about apps. Top level apps that need to require those libraries somehow. I would have thought it was completely reasonable for top-level app authors to require rubygems to pull in the libraries they need but judging by votes, apparently not. C'est la vie.


> Not that it makes any sense arguing further, but for the record, I was not talking about libraries, I was talking about apps.

An app is a library is an app.

> Top level apps that need to require those libraries somehow.

And Ruby has a built-in method for that. It's called `require`. So if an app, a library, a script or whatever needs another library, it requires it and is done.

> I would have thought it was completely reasonable for top-level app authors to require rubygems

No. Unless the toplevel app is never distributed out of controlled environments (where you do impose rubygems) or expands gems in some way and therefore needs to hook into it (e.g. a GUI gems manager à la synaptic for apt-get) there is no need for rubygems at the app level.

The usage of rubygems (or the lack thereof) is part of the execution environment (the state of the machine the app is run on), not part of the application. Maybe for security reasons all libraries are deployed manually and $LOAD_PATH is handled likewise, maybe the guy uses bundler (http://github.com/wycats/bundler/tree/master) or rip (http://hellorip.com/) and doesn't want or need rubygems, maybe the user goes through his OS's package manager of choice (be it yum, apt-get, ports, …) because he likes having all package handling across his machine in a single place and piece, or maybe the app's user does indeed use rubygems. But as the application/script/library author, that's none of your business.

Requiring rubygems in your distributed code (unless you're in specific wrapper contexts or, once again, you're building on top of rubygems and expanding it in some way) means you're putting your nose where it doesn't belong: you're forcing environmental decisions on your users.

If you want to package your lib/app as a gems, that's fine and way cool of you, but that doesn't imply requiring rubygems at runtime.


"An app is a library is an app."

I've belated realised that you're either a really good troll or you don't have the first fucking clue what you're talking about. Well done, you got me.


Whoever this guy is, he really needs to pull his head out of his ass.

The author is a smart guy. Major contributor to Sinatra, developer at Heroku, etc.

You might be right about the rubygems issue, but the random bile and personal attacks make it hard to take you seriously.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: