Setting up rubygems without root access
Recently we had to install our rails app on a box, but we didn't have root access. The machine had ruby 1.8.6 and rubygems 0.9.6 (ouch). We can live with Ruby 1.8.6; but to run modern rails, we needed modern rubygems.
The rubygems install page has a helpful section on how to install locally without root access. Note: be sure to add export GEM_HOME=~/rubygems/gems to your .bashrc or your .bash_profile or else the next time you log in, your system gets confused again.
$ mkdir rubygems
$ cd rubygems-a.b.c
$ export GEM_HOME=~/rubygems/gems
$ ruby setup.rb --prefix=~/rubygems
Unfortunately, this didn't go as smoothly as I hoped. The result:
" `gem_original_require': no such file to load -- rubygems/exceptions"
and many other similar error messages.
The issue was that since the server installation already had an old version of rubygems installed, my local gem script was calling up the old rubygems files, but using my new GEM_HOME. A big mess.
What needs to happen is that your new gem executable needs to load your new rubygems files, and work with your new GEM_HOME. There may be a better way to do this, but I have found a workable solution for my case. It involves messing with the executable files that rubygems installs.
If you take a look at your gem executable, you'll see it is just a text file, a ruby program that executes itself.
$ cat ~/rubygems/bin/gem
#!/usr/local/bin/ruby
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
require 'rubygems'
require 'rubygems/gem_runner'
require 'rubygems/exceptions'
...
If you are familiar with shell scripts, you'll know that the first line (the shebang) specifies the binary to use to process the file. In this case, its #!/usr/local/bin/ruby. In general this is great. Ruby loads up the file and runs the script and magic happens. But what if the require 'rubygems' line is loading up the wrong rubygems?
We need to tell ruby where to find our custom rubygems libraries. Luckily, ruby has an option for this, -I path/to/lib. So, all we need to do is open up our gem executable and modify the shebang line to include this option.
$ vim ~/rubygems/bin/gem
#!/usr/local/bin/ruby -I ~/rubygems/lib
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
require 'rubygems'
require 'rubygems/gem_runner'
require 'rubygems/exceptions'
This tells the ruby interpreter to start the process with our custom path in the include path. If we have a newer version of the rubygems library there, they get required instead of the old versions. I can now install gems locally into my GEM_HOME without needing root access like so:
$ gem install mongrel
But that's not all. mongrel also installs its own executable, and when you try to run it, it will require rubygems. And yes, you guessed it, it will find the old version of rubygems and get completely confused. So again, we need to go into the executable file ~/rubygems/gems/bin/mongrel_rails and modify the shebang line.
As far as I can tell, you would need to do this for each and every gem that installs its own executable.
Update: after further consideration, using the $LOAD_PATH environment variable would probably be more robust, but my app is already installed. Perhaps you will let me know how it goes with $LOAD_PATH
installing mysql gem on MacOS X Leopard
Using Rails 2.1.1, I get this warning about the mysql libraries associated with Rails:
The bundled mysql.rb driver has been removed from Rails 2.2. Please install the mysql gem and try again: gem install mysql.
As many have noted, the suggestion of `gem install mysql` doesn't seem to work well on the vanilla Leopard install with the standard MySQL pre-compiled binary. I followed lots of good advice from wonko, jlaine, hivelogic, and Seth Willits, but finally none of it worked.
Using the command from wonko:
sudo env ARCHFLAGS="-arch i386" gem install mysql -- \
--with-mysql-dir=/usr/local/mysql --with-mysql-lib=/usr/local/mysql/lib \
--with-mysql-include=/usr/local/mysql/include
got me the ulong compile error mentioned by jlaine,. Unfortunately, jlaine's instructions didn't work for me, the manual install step doesn't seem to really install anything. I realized I had to take it step further by modifying the source of he gem itself.
In order to fix the compile error in mysql.c, it helps to understand how the gem install command works. First, gem goes online to find the correct file, then downloads the packaged .gem file to your local gem cache. Then, gem unpacks the .gem and runs extconf.rb and make/make install. From reading extconf.rb, one can see that the mysql gem uses a file called mysql.c.in as a template to build a properly configured mysql.c, which then gets compiled into the C library that we will use.
$cd /Library/Ruby/Gems/1.8/cache
$sudo gem unpack mysql-2.7.gem
$cd mysql-2.7
This gives you the source of the gem. Open mysql.c.in to add the single line we need.
#define ulong unsigned long // quick fix so that it compiles on my machine
Then we need to repack the gem, copy it to the cache folder, and install our customized version using the command above.
$sudo gem build mysql.gemspec
$sudo mv mysql-2.7.gem ../mysql-2.7-CUSTOM.gem
$sudo env ARCHFLAGS="-arch i386" gem install mysql-2.7-CUSTOM.gem -- \
--with-mysql-dir=/usr/local/mysql --with-mysql-lib=/usr/local/mysql/lib \
--with-mysql-include=/usr/local/mysql/include
All this for one line of code...but finally:
$ gem list mysql
*** LOCAL GEMS ***
mysql (2.7)
Thankfully, most of the time we don't need to go through all this just to instal a library. This sort of thing happens rarely. But its great to know that as long as you have your command line, a good compiler, and some detective skills, you can fix many problems on your own!
kudelabs public code repository

We have started a new code repository at http://github.com/kudelabs. We will be using this to host our own plugins, utility files, and example code that we wish to make public. Hopefully, something here is of use to others in the community. If you find ways to improve upon our code, we will be happy incorporate your ideas as well. We'll be posting new code when it is ready, you can use github's "follow" feature to learn about new items.
So far I am impressed with github's features, there really isn't anything quite like it. I look forward to interacting with more developers through the site.
Rake task to help manage svn rename
$rake svn:rename[old_name,new_name] # notice no spaces
And here is the code:
namespace :svn do
FILES_TO_RENAME = [ "app/views/%s",
"app/controllers/%s_controller.rb",
"app/models/%s.rb",
"test/unit/%s_test.rb",
"test/functional/%s_controller_test.rb",
"test/fixtures/%s.yml"]
task :rename, :from, :to do |t, args|
FILES_TO_RENAME.each do |s|
from_f = s % args.from
to_f = s % args.to
if File.exists?(File.expand_path(from_f))
puts "Renaming #{from_f} -> #{to_f}"
puts %x[svn mv #{from_f} #{to_f}]
else
puts "Skipping #{from_f}. File not found."
end
end
end
end
Please leave comments if you see a way to improve this. Feel free to modify it to your needs and tell me about it.
Rubob (Ruby Object Browser) 0.0.3 released
After literally a year of not finding time for finishing touches, I decided to finally just release what I have. It works fine, after all.
Rubob is based on a little tool I wrote together with Matthias Hopf in 1997 or so to play with the Java Reflection API. When I started working with Ruby almost a decade later, I realized how much easier it would be in Ruby, so I rewrote it. And then it sat there...
So what does it do?
Rubob generates a hyperlinked Web-view of your program while it runs. It can very easily be added to any existing application (one line of code).
With Rubob, every object in the system has a corresponding URL. When you access that URL, Rubob generates a Web page that contains a human readable version of the object. All instance variables are hyperlinked to the URL for their value; so you can click your way through from object to object to explore the state of your program while it's running.
Certain classes, such as Array and Hash, have a custom representation that makes their content easier to explore.
You can add your own custom representation of objects using a simple API that I'll explain when I have some time.
Here is the code.
Enjoy!