Friday, May 15, 2009

Tip: Compiling the Postgres Gem for Ruby 1.9.1

[EDIT (2010-JAN-16): The original postgres gem has been replaced by ruby-pg. If you are having the problem below, try installing the pg gem via sudo gem pg install.]


I compiled a fresh copy of Ruby 1.9.1 onto my MacBook Pro and proceeded to install Ramaze, Sequel, Thin. Things went well and I was happy... that is, until I tried to install the postgres gem. I'm talking the C-extension one, which runs so much faster than the native one that it isn't even funny.

$ sudo gem install postgres

That's when it happened: bam! exception!

/usr/local/bin/ruby extconf.rb install postgres
extconf.rb:4:in `<main>': uninitialized constant PLATFORM (NameError)

No good. How am I supposed to develop enterprise Ruby software when I cannot connect to the database?!

What Happened

After poking around on the internet, I discovered two things about Ruby 1.9.1:

  1. The PLATFORM environment variable is now RUBY_PLATFORM, and
  2. The C macros for working with a Ruby Array changed.

The Solution

To solve this problem, one could learn what to do and hand-change all the code. This is a waste of time. I set-up a couple sed filters instead. Thus, to get your postgres adapter working, just do the following:

$ cd /usr/local/lib/ruby/gems/1.9.1/gems/postgres-
$ sudo sed "s/PLATFORM/RUBY_PLATFORM/" extconf.rb > ./extconf.rb
$ sudo ruby extconf.rb
$ sudo sed "s/RARRAY(\([_a-zA-Z0-9]*\))->ptr/RARRAY_PTR(\1)/; s/RARRAY(\([_a-zA-Z0-9]*\))->len/RARRAY_LEN(\1)/; s/row->len/RARRAY_LEN(row)/; s/row->ptr/RARRAY_PTR(row)/" postgres.c > ./postgres.c
$ sudo make
$ sudo make install


While I have been successfully using this patch, I have not tested it in a production environment. Therefore, you should put this patch through its paces before using it on anything critical.

Lastly, but definitely most importantly, I am NOT liable for anything bad that may happen as a result of using this patch. It is up to you to thoroughly test it for any problems, which may include (but are not limited to) loss of data on your system, loss of data on your database, corruption of your Ruby installation, self destruction of your hard drive, spontaneous combustion of your printer, Swine flu infection, SARS transmission, broken lawn mowers, and rancid ice cream.


lobo_tuerto said...

I had to chmod my extconf.rb file so I can write in it (sudo wouldn't cut it).

After that, the first sed command, truncates the file to 0 bytes.

I'm on Ubuntu 9.04, do you know what's going on?

Paul said...

In response to lobo:

All you need to do to get this running on Ubuntu 9.04 is direct the sed commands to temporary files and then move them over the originals.

$ cd /usr/local/lib/ruby/gems/1.9.1/gems/postgres-
$ sudo sed "s/PLATFORM/RUBY_PLATFORM/" extconf.rb > ./extconf.bck
$ sudo mv extconf.bck extconf.rb
$ sudo ruby extconf.rb
$ sudo sed "s/RARRAY(\([_a-zA-Z0-9]*\))->ptr/RARRAY_PTR(\1)/; s/RARRAY(\([_a-zA-Z0-9]*\))->len/RARRAY_LEN(\1)/; s/row->len/RARRAY_LEN(row)/; s/row->ptr/RARRAY_PTR(row)/" postgres.c > ./postgres.bck
$ sudo mv postgres.bck postgres.c
$ sudo make
$ sudo make install

Thanks for advice on how to get this working Paploo, very handy.

Anonymous said...

You can use 'sed -i' to edit a file in place. No need to type the filename twice.

Anonymous said...

Amazingly enough (or not?) I was doing a fresh install with pg and was still getting the error.

Well, I should say that installing pg worked fine, but when trying to start rails I kept getting a pg does not exist error. But both pg and postgres show the exact same gem when installed. Paths are set correctly, etc.

So I ran your patch and now my server boots fine. Go figure!

Either way, thank you!

Paploo said...

@Anonymous on February 4, 2010 6:18 PM:

It sounds like you have a conflict going on. You may want to remove all instances of the previous postgres gem and see if that makes pg work. (I'd advise switching to it if you can!)

If it is still overriding, it is also possible that there is an installation of a postgres gem in an odd place that is overriding yours. (This sounds odd, but I've seen this happen on non-standard installs).

val2many said...

"gem install pg" works for me on Debian with no trouble at all.
You probably figured, but I thought I'd mention ...

Paploo said...

@val2many: Yeah, I figured that out after getting a bug report reply from the pg team. I edited the the post about 6 months ago with a note at the top bout that. :)

dafevara said...

i tried ruby-pg and i applied the explanation above and works fine.