I’m scared. Recently our community (Rails, and Ruby programming) was blessed with some great, great software by Yehuda Katz, Bundler.

This software freed us from a lot of the problems associated with the sudo/no-sudo problems with gems, and really liberated us from every problem with Ruby Gems I’d ever had.

Then, something happened – too many chefs spoiled the soup, and now we have carlhuda implementation, required for Rails 3 – which hit beta today, and has a dependency on this modified version, which seems like a system to manage gems on a system designed to manage gems.

Frankly, I’m scared – either I missed something, and I’m falling out of touch with our community’s needs, or a single framework is going to ruin it again for all the people who have worked so hard on bringing equality back to Ruby web development.

I can’t shake the feeling that Rails has forced features into a great piece of software, making it much more confusing to use and offering a bunch more ways to cock things up.

I really hope I’m wrong.

A couple of weeks ago, I read an interesting tweet from Chris Wanstrath – it read a little something like this “Every time you use sudo to install a gem, an angel loses its wings”.

It got me to thinking, what exactly could he mean, we’ve all used sudo to install gems at some stage, and many of us don’t see a problem with it, at least I never had.

So, I came up with a few thins that were bugging me about it, and want to try and debunk a few of the myths about gems..

What about sharing gems with system processes, most notably Passenger mod_rails?

This one bugged me, if I install a gem – and I am developing – I do not want to have to install this gem twice, once for me, once for the system, and moreover – if I do install this gem twice – should I install the other one as the apache or www (delete as appropriate) user, or using sudo.

But the executables for my gems aren’t in my $PATH?

You have no excuse! When installing a gem, if it has a executable component (think haml . --rails and capify ., rake, etc) the installer process will warn you with a concise and clear explanation, the gist of which is that if you locally install a gem without ~/.gem/ruby/1.8/bin/ in your PATH then running these executables won’t work.

I don’t think this is an unfair sacrifice to make, and we’ve all altered our PATH for less; my only suggestion on this point is to make this change not in your local dot files, but in /etc/profile.

So, locally installed gems; works pretty nicely how should we make them available to our production application?

Firstly, make sure you are using some kind of declarative gem dependency specification personal taste aside I think any one of Bundler, Rip, Gem Installer or Rails’ own config.gem does a pretty good job – the key thing is that at deploy time, or before – you have a mechanism for determining what must be installed for your application server to run.

This can take a couple of forms – either you take the advice of Jay Fields and Ryan Bates, and unpack the gems – this leads to two further roads, do you bundle these into your SCM system, and deploy them each time, or defer this action to the server at deploy time, or take another option?

The plot thickens when you take into account login shells, versus non-login shells; Apache will ignore the /etc/profile file; as mentioned above unless you add the suggested line to /etc/apache2/envvars – the Apache documentation on this topic saysIf you wish to manipulate the operating system environment under which the server itself runs, you must use the standard environment manipulation mechanisms provided by your operating system shell.” – their documentation makes no mention of the envvars file – so there’s a good chance this is operating system dependant, the safest thing to do all round is package your gems with your application unless you have a smart system administrator to take care of the Apache configuration for you.

Advice: Let your system guys decide; and if you are the system guys, do what suits you best; I dare argue that in this case it is acceptable to sudo install the gem, for use by the system. If you must mess with your web servers configuration, do it in the start-up scripts; this way you can at least be declarative about these too.

/etc/profile Apache and /etc/apache2/envvars – and Macs

If you’re wondering why I’m suggesting using /etc/profile rather than your local dot files comes back to the question regarding installing your Passenger mod_rails gems using sudo or not; if your apache instance honours the /etc/apache2/envars file, you can add here a line like source /etc/profile and share system-wide configuration.

Note: Since I am neither responsible for any worthwhile deploys anymore, and I only develop on a Mac – my advice in this area might be a little short sighted!

How do I do it?

Well, I install local gems, and rely on config.gem at deploy time; this works perfectly for me, and also works quite nicely for sharing gems between different versions of Ruby using [Ruby Version Manager (a.k.a rvm)])(http://rvm.beginrescueend.com/) – which recently threw another spanner in the works in the form of Named Gem Sets which thankfully stays out of the way!

Feedback

Please discuss, I have a lonely comments system, or mention me on twitter @leehambley – I’d love some feedback from people on this, I’m sure there are smarter ideas than mine!

Often when writing a library for use by another application you are working on, or to release to the world, it’s handy to have your own Error and Exception classes (yeah, apparently there is a difference).

When doing that it’s not uncommon to just need an empty class with a specific name, so you can raise() one later, in cases such as this we often see code like this:

That’s fine, and it works too – but this might be a little prettier:

Class does also take a block, but I’m not sure how useful that might be, you can read all about it in the Ruby Class API Docs.

I hope this helps someone write smaller empty class definitions!

It’s often overlooked that in Capistrano tasks can call other tasks, for example internally we call many tasks when someone runs cap deploy.

Consider we have tasks that look something like the following, there are a few ways we could chain them together; I want to examine the merits of each very briefly:

As the example above stands, we can call a couple of tasks, cap one:greet which will output World or cap two:greet which will output Hello. Consider we implement a task called :greet which we could call like cap greet which would output Hello World. The most obvious idea might be to try something like:

This approach is interesting in that we can see how to call methods in other namespaces from the top namespace.

What if we were to decide that every time two:greetruns and says Hello we need one:greet to run and complete a task (in this case, greet the user with Hello World).. we could implement something like this:

By approaching this using the after() method ( there is also a before() method) it ensures whenever we call two:greet, that one:greet is called immediately after.

This may, or may not work for your situation; it may make sense for example to use after to always correct or set permissions when using Capistrano to deploy a configuration file.

It is worth pointing out that long-running jobs linked as after() tasks can be particularly unforgiving, as it isn’t always obvious what is calling the long running job.

These are simple techniques, and your mileage may vary!

I stumbled across this late last week, Chris Eppstein’s Compass requires HAML 2.1, this used to mean a manual installation of HAML from their Git master branch, and generally more fiddling than it was worth.

Chris was then good enough, somewhere around 0.6.10 (I think?) to change the dependency so you could use the Rubyforge hosted haml-edge gem that they maintain which currently represents 2.1.24. Then no more manually installed HAML, and back to being able to rely upon config.gem.

It turned out that late last week a system gem update installed HAML, after HAML edge, knowing this it’s obvious that it is going to break Compass, but I hadn’t realised until just now… so lesson to learn, reinstall any edge-tracking gems that may have been compromised during a system upgrade.

Just my 0.02$.

This comes up for me from time to time, so I’ve come up with a quick way of quickly removing a list of gems in one go…

You can see it is reliant on `ack` (sudo port install p5-app-ack / sudo apt-get install ack) … essentially it just removes them all through the standard gem facility, the –all switch stops gem asking which version you want to remove of certain things.

I had to make this because I was constantly doing the same thing to test config.gem settings in rails, and it was frustrating waiting for the CI server to blow up with dependency failures :)

I’m putting this here because I’m tired of Googling it, so here goes…

.. yep, that’s all there is to it.

Sed, and Find are amongst unix’s most useful tools – SED is a Stream EDitor, and is meant for processing text streams, which is great for searching and replacing inside files with a regular expression or other similar pattern.

And, Find is another great unix tool, and can be used to find files and directories with a number of options, at it’s most basic, it lists, all files and directories in the current directory.. whilst at it’s best, it can show all files edited between X and Y times, matching, or not a certain pattern.

These two tools are covered extensively in their own documentation, as well as in numerous books, and tutorials online.

I’ve chosen to show, and explain a simple way to use them together.

The man pages for sed and awk can be found here and here, and there is also more on wikipedia (sed, awk).

Sometimes, when deploying you’ll need to invoke a task from a spefic directory, when the following won’t do:

You may need to do the following:

You will quickly discover that that doesn’t work so well, as each run() creates its own subshell… so the CD run on one, won’t affect subsequent calls.. The not so obvious solution is to run this:

The example above is a little misleading, as it doesn’t pass the filenames from the find function to the javascript compressor, something like this following would, if that’s why you’ve come to read this….. caveat – is that the following line of code might make you blind!

Hope this helps!

It comes up from time to time, how to do multi-stage deploys without the hassle of messy files all over the place.

The truth of it is, for the most part, unless you have special role requriements, that you often dont’ need all these files, you can get away with a YAML configuration file.

More after the jump, as there’s quite a lot of code to go over in this article!!

Read the rest of this entry »