TL;DR

The backup gem contains a bug that causes it to crash when the HOME environment variable is not set. Notably, this is the case when jobs are started by ‘god’.

I have patched this and will soon send a pull request to the authors of the gem.

Read on to get a few hints on how to track down issues like this one.

The story of a painful bug hunt

0. Background

On several projects I’m using god to start and monitor daemon processes, especially resque workers. On one particular project, this just stopped working recently and as a workaround I had to start the resque workers manually under tmux.

Today I finally took the time to figure out what was going on.

1. Symptoms

In my god.conf I have a ‘resque’ watch configured which starts five workers. Here is the relevant snippet from god.conf:

num_workers = rails_env == 'production' ? 5 : 2
num_workers.times do |num|
  God.watch do |w|
    w.name     = "resque-#{num}"
    w.group    = 'resque'
    w.interval = 60.seconds
    w.env      = {"QUEUE"=>"*", "RAILS_ENV"=>rails_env}
    w.start    = "bundle exec bootup_rake -f #{rails_root}/Rakefile environment resque:work"
    w.dir      = "#{rails_root}"
...

When doing a “god start resque”, god tries to start up the workers but they crash almost immediately. If I do “ps aux | grep resque” within a few seconds I see the processes but then they just disappear.

2. What is god saying?

Finding the scroll that collects the utterings of god is easy:

/var/log/god.log

However, it quicly becomes apparent that god has nothing interesting to say:

I [2011-11-15 16:24:57]  INFO: Using pid file directory: /var/run/god
I [2011-11-15 16:30:55]  INFO: Syslog enabled.
I [2011-11-15 16:30:55]  INFO: Using pid file directory: /var/run/god
I [2011-11-15 16:39:30]  INFO: Syslog enabled.
I [2011-11-15 16:39:30]  INFO: Using pid file directory: /var/run/god
...

A bit of googling suggests that I try to run god in the foreground to see what is going on.

3. Non-daemonized god

So let’s see how god is being invoked:

root@foo:~# ps aux | grep god
root     27956  4.5  0.2 179304 19132 pts/1    Sl   10:12   \
   0:00 /usr/local/rvm/rubies/ruby-1.9.2-p290/bin/ruby      \
   /usr/local/rvm/gems/ruby-1.9.2-p290/bin/god -P /var/run/god.pid -l /var/log/god.log

We need to make a few tweaks:

  • don’t send output to a log file (remove -l)
  • load the config file with -c <config>
  • keep it in the foreground with -D

So our command becomes:

root@foo:~# /usr/local/rvm/rubies/ruby-1.9.2-p290/bin/ruby \ 
   /usr/local/rvm/gems/ruby-1.9.2-p290/bin/god             \
   -P /var/run/god.pid -c /etc/god.conf -D

This yields slightly more interesting output. Here are the lines for the worker ‘resque-1′:

I [2011-11-16 10:17:13]  INFO: resque-1 move 'unmonitored' to 'init'
I [2011-11-16 10:17:13]  INFO: resque-1 moved 'unmonitored' to 'init'
I [2011-11-16 10:17:13]  INFO: resque-1 [trigger] process is not running (ProcessRunning)
I [2011-11-16 10:17:13]  INFO: resque-1 move 'init' to 'start'
I [2011-11-16 10:17:13]  INFO: resque-1 start: bundle exec bootup_rake \ 
   -f /var/www/foo/current/Rakefile environment resque:work
I [2011-11-16 10:17:13]  INFO: resque-1 moved 'init' to 'start'
I [2011-11-16 10:17:13]  INFO: resque-1 [trigger] process is running (ProcessRunning)
I [2011-11-16 10:17:13]  INFO: resque-1 move 'start' to 'up'
I [2011-11-16 10:17:13]  INFO: resque-1 moved 'start' to 'up'
I [2011-11-16 10:17:13]  INFO: resque-1 [ok] memory within bounds [8952kb] (MemoryUsage)
I [2011-11-16 10:17:14]  INFO: resque-1 [ok] process is running (ProcessRunning)

OK, maybe that’s not so interesting after all. God starts the process and is satisfied with that.

What IS interesting is the fact that this actually works! The resque workers keep running and start processing jobs.

4 WTF?

So when I start god non-daemonized, it works. When god is started with ‘service god start’, it does not.

I need a way to see the log output from god when it is running in daemonized mode. This turns out to be as simple as:

god log resque

By default this gives me the output from the first worker in the group. I won’t repeat it here, but it is exactly the same as when running god in the foreground.

It seems to be safe to assume that god is behaving the same way whether started by me or via /etc/init.d/god. To be sure I also tried starting it by executing the exact two lines from this file. Same result.

5. Inspecting the environment

I have suspected for a while that this issue has to do with the environment in which the rake command is being run. This seems to be the only major source of difference between the working and the non-working experiments.

So I need to know the environment in which the failing rake invocations are being run. I know that for all running processes, the environment is available in the file /proc/<pid>/environ. But how can I get to this file when the process dies within seconds?

My solution is to run the following command immediately after god tries to start the workers:

less -f /proc/`ps aux | grep resque | head -1 | cut -d ' ' -f 4`/environ

What this does is

  • ps aux | grep resque finds the process info for the about-to-die resque workers
  • head -1 grabs the first one
  • cut -d ‘ ‘ -f 4 cuts out the PID (fourth field when using a space as the delimiter)
  • This PID is then used as part of the path passed to the outer less command

The environ file is in some kind of binary format (which is why I need -f on the less command) the details of which I haven’t bothered to look up.

I don’t really need to, because after running the above command I see this in my iTerm:

GEM_HOME=/usr/local/rvm/gems/ruby-1.9.2-p290^@TERM=xterm^@IRBRC=/usr/local/rvm/r\
ubies/ruby-1.9.2-p290/.irbrc^@MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-1.9.2-p290\
^@QUEUE=*^@rvm_path=/usr/local/rvm^@PATH=/usr/local/rvm/gems/ruby-1.9.2-p290/bin\
:/usr/local/rvm/gems/ruby-1.9.2-p290@global/bin:/usr/local/rvm/rubies/ruby-1.9.2\
-p290/bin:/usr/local/rvm/bin:/var/www/foo/shared/bundle/ruby/1.9.1/bin:/usr/loca\
l/rvm/gems/ruby-1.9.2-p290/bin:/usr/local/rvm/gems/ruby-1.9.2-p290@global/bin:/u\
sr/local/rvm/rubies/ruby-1.9.2-p290/bin:/usr/local/rvm/bin:/usr/local/sbin:/usr/\
local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games^@PWD=/var/www/foo/releases/20\
111115153743^@LANG=en_US.UTF-8^@SHLVL=1^@BUNDLE_GEMFILE=/var/www/foo/releases/20\
111115153743/Gemfile^@RAILS_ENV=production^@rvm_ruby_string=ruby-1.9.2-p290^@GEM\
_PATH=/usr/local/rvm/gems/ruby-1.9.2-p290:/usr/local/rvm/gems/ruby-1.9.2-p290@gl\
obal^@RUBYOPT=-I/usr/local/rvm/gems/ruby-1.9.2-p290/gems/bundler-1.0.18/lib -rbu\
ndler/setup^@BUNDLE_BIN_PATH=/usr/local/rvm/gems/ruby-1.9.2-p290/gems/bundler-1.\
0.18/bin/bundle^@RUBY_VERSION=ruby-1.9.2-p290^@

Notice that the variables are separated by some byte that less renders as “^@”. Good!

6. Reproducing the bug

Off to Emacs to transform this into something useful. I won’t bore you with the details, but a quick keyboard macro transforms the above into:

export GEM_HOME=/usr/local/rvm/gems/ruby-1.9.2-p290
export TERM=xterm
export IRBRC=/usr/local/rvm/rubies/ruby-1.9.2-p290/.irbrc
export MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-1.9.2-p290
export QUEUE=*
export rvm_path=/usr/local/rvm
export PATH=/usr/local/rvm/gems/ruby-1.9.2-p290/bin:/usr/local/rvm/gems/ruby-1.9.2-p290@global/bin:\
   /usr/local/rvm/rubies/ruby-1.9.2-p290/bin:/usr/local/rvm/bin:/var/www/foo/shared
export PWD=/var/www/foo/releases/20111115153743
export LANG=en_US.UTF-8
export SHLVL=1
export BUNDLE_GEMFILE=/var/www/foo/releases/20111115153743/Gemfile
export RAILS_ENV=production
export rvm_ruby_string=ruby-1.9.2-p290
export GEM_PATH=/usr/local/rvm/gems/ruby-1.9.2-p290:/usr/local/rvm/gems/ruby-1.9.2-p290@global
export RUBYOPT=-I/usr/local/rvm/gems/ruby-1.9.2-p290/gems/bundler-1.0.18/lib -rbundler/setup
export BUNDLE_BIN_PATH=/usr/local/rvm/gems/ruby-1.9.2-p290/gems/bundler-1.0.18/bin/bundle
export RUBY_VERSION=ruby-1.9.2-p2

Back on the server, I clear all existing environment vars with a snippet I found here:

unset  $ ( /usr/bin/env | egrep '^(\w+)=(.*)$' | \
  egrep -vw 'PWD|USER|LANG' | /usr/bin/cut -d= -f1);

Next, I paste all the exports above into iTerm and finally I am ready to try starting the worker again.

Voila!! It crashes:

rake aborted!
can't convert nil into String
/var/www/foo/shared/bundle/ruby/1.9.1/gems/backup-3.0.16/lib/backup.rb:40:in `join'
/var/www/foo/shared/bundle/ruby/1.9.1/gems/backup-3.0.16/lib/backup.rb:40:in `<module:Backup>'
/var/www/foo/shared/bundle/ruby/1.9.1/gems/backup-3.0.16/lib/backup.rb:8:in `<top (required)>'
...

Here are the lines around line 40 of backup.rb:

##                                                                                                                                                                                                                                                                                                                                                                      
# Backup's Environment paths                                                                                                                                                                                                                                                                                                                                            
PATH               = File.join(ENV['HOME'], 'Backup')
DATA_PATH          = File.join(ENV['HOME'], 'Backup', 'data')

Ah, so the backup gem assumes that the HOME environment variable is set. If not, it crashes.

7. Done

Fortunately the source for “backup” is on Github, so I could easily fork the project and apply the very simple patch that was needed.

If you need to run scheduled jobs in your Rails app (!= background jobs as in Resque), you should use the excellent whenever gem.

However, one detail that is really easy to miss is which shell environment the cron job actually runs under.

bundle: command not found

And an easy way to confuse yourself even further is by trying to debug issues in this area by:

  1. Logging into your  server as the deployment user
  2. Doing crontab -l to see which entries whenever installed
  3. Testing an entry by cut’n’pasting it to the shell prompt
The outcome will not be reliable, because you’re running it from a login shell and cron is not. So for example, your rbenv shims may be in the path while testing, but cron does not load your .bashrc or .bash_profile files.

On a project I work on, the staging and production machines are currently quite different. In production we use RVM (globally installed) while staging has rbenv locally installed for the deployment user.

So in staging I need to assume that no binaries are available and use the full path to bundler, in my case /home/passenger/.rbenv/versions/1.9.2-p290/bin/bundle.

(I know, symlinking this to eg. /usr/local/bin/bundle would probably be more elegant, but I actually like the reminder of where my ruby is actually installed. I don’t spend much time on the servers, so I tend to forget.)

Running stuff only on certain stages

EDIT: See Markham’s comment for a better way to do achieve the same result.

Another issue I struggled with for a while is how to schedule jobs only in production. For example, I don’t want to run S3 backups from staging.

I use capistrano/multistage, so I needed to inspect the value of the current “stage” from schedule.rb. It turns out that by including this:

require 'capistrano/ext/multistage'

set :whenever_environment, defer { stage }
require "whenever/capistrano"

…the stage is available in schedule.rb as @environment. Very simple, but it took some googling to find.

Example schedule.rb

Below is my anonymized schedule.rb. It should be pretty self explanatory, post questions in the comments if not.

def production?
 @environment == 'production'
end

set :bundler, production? ? "gp_bundle" : "/home/passenger/.rbenv/versions/1.9.2-p290/bin/bundle"

job_type :gp_rake, "cd :path && RAILS_ENV=:environment :bundler exec rake :task --silent :output"
job_type :gp_runner, "cd :path && :bundler exec rails runner -e :environment ':task' :output"
job_type :gp_bundle_exec, "cd :path && RAILS_ENV=:environment :bundler exec :task"

every 5.minutes do
 gp_rake "thinking_sphinx:index"
end

every 30.minutes do
 gp_runner "FooBar.update"
end

every 1.day, :at => "4:00am" do
 gp_runner "Baz.purge_inactive"
end

if production?
 every 1.day, :at => "4:00am" do
   gp_bundle_exec 'backup perform --trigger my_backup --config-file config/backup.rb --log-path log'
 end
end

EDIT: Jakob Skjerning posted this snippet in the comments:

job_type :rake, “cd /var/www/appname/#{environment}/current && /home/appname/.rvm/gems/ree-1.8.7-2010.02@appname-#{environment}/bin/bundle exec /home/appname/.rvm/wrappers/ree-1.8.7-2010.02@appname-#{environment}/rake –silent RAILS_ENV=#{environment} :task :output”

One of the things that bothers me the most in software development is when you come across a problem for which there simply is no nice solution to be found. You come up with some ugly hack and get the job done, but the nagging feeling of having fallen short lingers for days.

Problem in question: A project I’m working on sells stuff and uses a payment gateway for this. API access is expensive so we’re opting for the proxy method, meaning that the page that reads credit card information is actually served by the payment provider. It looks something like this:

http://epay.dk/proxy.cgi/http://myshop.com/payment

This means that our /payment page is a very special case. All asset paths must be relative, ie. images/foo.png instead of /images/foo.png. In contrast, links must be absolute, http://shop.com/about instead of /about.

I want the rest of the site to follow normal Rails conventions, so I need to special case this very page. This in itself is a challenge, because as it turns out my ugly hack will affect the application layout as well.

I first tried a few different routes:

  1. Override url_for and set :path_only => false. This solves only half of the problem (asset paths would still be wrong) and turned out to be painful because of the two different url_for implementations. Figuring out why is left as an exercise for the reader because frankly, I can’t be bothered to explain why. Leave a comment if you want to know.
  2. Define some default_url_options. For some reason, I never got this to work reliably, and after some time of fruitless digging trough the Rails source, I abandoned the idea.
  3. Create middleware that kicks in only if controller == Xxx and action == Yyy. It would then process the HTML and change href=”/…” instances to be relative etc. You may object that this is a terrible way of abusing the middleware system, but if it had worked, it would actually have been the least intrusive option. The reason it broke down was unexpected and enlightening: I was able to rewrite the HTML, but afterwards the Apache module pagespeed rewrote it again to optimize CSS includes etc. Obviously this only happened in our production environment, so it took me a couple of hours to track down.
So it would seem that my quest to solve this (somewhat) elegantly had failed. So be it. Time to resort to the nasty hacks.

The solution

Warning: You will be appalled.

What I ended up doing was:

  • In views/layouts/application.html.haml, I only include JS and CSS if we’re not on the payment page.
  • In the payment view, I include all JS/CSS like this (notice that the path does not begin with a slash): %script{ :src => “javascripts/jquery.min.js”, :type => “text/javascript” }
  • Also in the payment view, I added some JS that absolutifies all links. It looks like this:
  $('a[href^="/"]').each(function (idx) {
    fullUrl = "http://myshop.com" + $(this).attr("href");
    $(this).attr("href", fullUrl);
  });

Conclusion

I have created some code that works, but which I’m really, really unhappy about. I hope that some day I’ll come up with a better idea and fix this, but I doubt it. Suggestions are obviously welcome – please leave a comment.

On a project, I have a “Revision” resource and URL’s like

http://foobar.dev/revisions/1

Now suddenly the client wants to rename “revision” to “edition”, so all URLs should be changed to the format

http://foobar.dev/editions/1

Unless I’m missing something in the Rails docs, there is no option to change the base part of the path without renaming the resource itself. Actions can be renamed, eg. “nuevo” instead of “new”, but I don’t think the path segment for the resource name can be changed (please correct me if I’m wrong).

I guess the proper way to go would be to rename everything: The AR model, all helper calls, controllers, tests etc. Even with lots of automation, this would be a really annoying task and I’m not inclined to spend time on this right now. Who knows if the client will change his mind again?

So instead, I ended up changes the resource from

  resources :revisions

to

  resources :editions, :controller => "revisions", :as => "revisions"

I’m changing the name of the resource, but the :controller option makes sure the right controller is still called, and the :as option controls the generation of path helpers (so I can keep using eg. edit_revision_path).

Remember to make the same change for nested resources.

EDIT: As Rasmus and Jakob point out, the :path option sets the actual path, not a prefix. I have made some minor updates to the Rails docs to correct this (most instances were already fixed).

Today, I found a bug in Rails.

On a project, I need to mail PDF files to users, and I would like to use PDFKit for that. The contents of the PDF are generated by rendering a view, but I don’t really want PDFKit to hit the server to get the content. Both because this breaks down in unit tests where the server may not be running, but also because there’s just no reason to go through the entire stack.

So I decided to generate the HTML with render_to_string, then convert it to PDF with PDFkit, and finally mail it to the user.

However, it turned out that this doesn’t work. Here is a minimal example:

class NoteMailer < ActionMailer::Base
  default :from => "from@example.com"

  def foo
    @notes = []
    render_to_string(:template => "notes/index.html.erb")
    # self.instance_variable_set(:@lookup_context, nil) # <-- Workaround
    mail(:to => "example@example.com")  
  end
end

It turns out that the call to render_to_string initializes the @lookup_context of the controller (== mailer in this case). The lookup context is the object that is responsible for locating templates to render, so it contains (among other things) a list of template extensions to look for.

The call to mail() renders the actual mail, but the mailer now reuses the lookup context that was created by render_to_string. This prevents it from finding the mail template, which is (in this example) named “foo.text.erb”, because the lookup context doesn’t recognize the “.text.erb” extension.

A workaround is to manually clear the lookup context on the mailer after the call to render_to_string, but obviously this is a really bad solution.

Although I basically agree with the Pragmatic Programmers’ old advice about learning a new programming language each year, the time has come for me to slow down.

I have been programming for many years and I know a lot of different languages. Many of them are boring and similar (eg. Java, C#, C++), some are not boring but similar (Ruby, Python) and some are completely different (Clojure, Common Lisp, JavaScript).

I’m well aware that I could learn a lot by studying Haskell or diving deeper into Javascript, but I’m going to take this year off.

Why? Very simple. I still have so much to learn from Clojure. I could write at length about the virtues of functional programming or about how Clojure takes advantage of the JVM. I could go on and on about the REPL, Java libraries, infinite lazy sequences (list of all primes, anyone?), the exceptionally smart community members and so on. But others have already done this much better than I could. For a great introduction to the language itself, go watch the intro videos by Clojure creator Rich Hickey. For all the surrounding stuff, there are lots of interesting blogs to read.

Likewise, although I have a lot of experience with both Ruby and Rails, I’m not done learning here either. Especially, I need to tune my Emacs to achieve better code navigation and debugging support.

Two languages that I really like. This year, I’m going to focus, not diversify.

JRuby/Clojure integration

December 21, 2010

I recently did a demo at an aarhus.rb meeting, showing how to call Clojure code from a Rails app. Specifically, I wanted to try using the very impressive Incanter library which is written in Clojure. This is not just a contrived example – Incanter is something you’d want to integrate with if you needed to do something statistics related.

This post is a walkthrough of how I got a very simple demo app running. It displays a histogram and allows the user to enter the size of the normal distribution sample.

NOTE: The finished Rails app can be found on Github.

1. Set up the basics

As with any other project, I am using RVM for managing multiple (J)Ruby implementations and keeping gemsets project-specific.

So first, create a directory for the Rails app. Inside that directory, create a .rvmrc file containing the following line:

rvm --create jruby-1.5.2@jruby-clojure-demo

Now do a “cd .” to have RVM pick up this file. This switches to jruby-1.5.2 (which must be installed, see RVM docs) and a newly created “jruby-clojure-demo” gemset.

We obviously need Rails for this demo:

gem install rails

This installs Rails 3.0.x as of this writing. Since this takes a little while to complete, fire up another terminal and let’s move on.

2. Fetch all the JARs we need with Leiningen

Leiningen is a build/dependency management tool for Clojure. I’m not using it to build anything for this demo, but it is useful for pulling down all the JARs we need.

Install Leningen, then create a new project with “lein new”, eg. in ~/tmp. Modify the project.clj file to look something like this:

(defproject incanter-test "1.0.0-SNAPSHOT"
  :description "FIXME: write"
  :repositories {"incanter" "http://repo.incanter.org"}
  :dependencies [[org.clojure/clojure "1.1.0"]
                 [org.clojure/clojure-contrib "1.1.0"]
                 [org.incanter/incanter-full "1.0.0"]]
  :dev-dependencies [[swank-clojure "1.2.1"]])

Finally run “lein deps” to have Leiningen download all required JAR files into lib/. This also takes a while, but now our Rails gem is installed and we can move on.

3. Create the Rails app

We use -O to skip activerecord:

rails new . -O

Next, add jrclj to the Gemfile. This is a JRuby/Clojure bridge created by Kyle Burton, and it’s the heart of this integration.

gem 'jrclj'

Do a “bundle install” to install all gems required by our new Rails project.

4. Enabling Clojure integration in the Rails project

To allow us to call Clojure code from the Rails project, we need to load all the JARs we downloaded in step 2.

First, create a “deps” folder inside the Rails app and copy all the JARs into it. Then, insert the following before the Bundler#require call in application.rb:

require 'java' 
Dir["#{File.dirname(__FILE__)}/../deps/*.jar"].each do |jar|
  require jar
end

This code needs to be executed before the Bundler call because the imported JARs are needed for the JRClj bridge to initialize properly.

5. Creating the histogram view

It’s time to call some Clojure code to render our view. I’m not showing how to create the actual Rails controller, the view or the simple form that collects the size attribute. See the Github repo for a working example.

To create the histogram, we use the method incanter.charts/histogram. The input to this method is the result from incanter.stats/sample-normal, and we save its output with incanter.core/save.

The output of incanter.core/save is a stream of PNG data. It should have been possible to simply save this data into a new ByteArrayOutputStream (yes, with JRuby you can just instantiate that class), but because of what looks like a glitch in the JRuby/Clojure bridge, this did not work. It looks like the return types may be wrong in some cases, but I haven’t found time to investigate yet.

So I resorted to a dirty hack: Dropping the PNG data into a file in public/images and simply inserting an image_tag into the view to render it. Thread-safe? I don’t think so :-)

    clj = JRClj.new
    %w{core stats charts}.each { |l| clj._import("incanter.#{l}") }
    clj.eval clj.read_string "(incanter.core/save \
                                (incanter.charts/histogram \
                                   (incanter.stats/sample-normal #{@size.to_i})) \
                                 \"#{::Rails.root.to_s}/public/images/out.png\")"

So what I’m doing here shows one of the two ways you can use JRClj: Evaluating a string containing Clojure code. The clj.eval call above evaluates to the value of the call to incanter.core/save, ie. the outermost sexp in the string.

The other, arguably cleaner and more Ruby-like mode to go, is to instantiate a JRClj object (like above), then call the Clojure functions as if they were Ruby function, with the difference that dashes in method names are replaced with underscores:

jruby-1.5.2 > clj = JRClj.new
=> (truncated...)
jruby-1.5.2 > clj._import("incanter.stats")
=> (truncated...)
jruby-1.5.2 > clj.sample_normal(1000).take(5)  
=> [-1.67885083887929, 0.332869879174951, -0.178234653916897, -0.382876843067349, 1.16325259920326]

Appendix: A Clojure-enabled IRB

I think most Ruby programmers agree that the IRB is a very useful thing, and it becomes even more useful when playing with stuff like JRClj.

Included in the JRClj documentation is a small script that loads the necessary JAR files and fires up an IRB session. I used this while working on the demo, and the script can be found as “jrepl” in the root of the Github repo.

Today I was going through some trouble setting up an existing Rails project I need to do some work on.

The project uses the Postgres database and Sphinx to provide search functionality. Installing Postgres is easy using the official DMG. Installing Sphinx using Homebrew is also very easy:

sudo brew install sphinx

That should be it, right? Unfortunately, not quite. This did install Sphinx, but without Postgres support. If you build TS yourself, Postgres support is enabled by adding the –with-psql option when calling ./configure. I looked through the brew documentation but didn’t find any way of passing this option to the configure command that brew executes.

Finally, it occurred to me to look into the brew “formula” for Sphinx. This is just Ruby code, and the source of the problem was easy to spot: It turns out that the formula installs Postgres support automatically if it detects that Postgres is installed. The problem was the method it used for detecting this:

config_args << “–with-pgsql” if `/usr/bin/which pg_config`.size > 0
So if pg_config had been in my path, it would have worked. But it wasn’t, simply because I hadn’t yet gotten around to adding /Library/PostgreSQL/8.4/bin to my PATH variable.
Did this, reinstalled sphinx, all went well.

Here’s a surprisingly insightful blog post from Matt Aimonetti. Yes, the guy with the “Perform like a pr0n star” CouchDB presentation.

I really hated this guy when the heated debate about his talk was running (when was this…some time last year?). He responded to the comments he got with such arrogance and lack of respect for other people’s emotions that a lot of us were appalled. I really felt (and still feel, actually) that he did damage to the reputation of the entire Ruby community. The fact that DDH stood behind him obviously just made everything worse.

Now all this seems to be forgotten, and that’s certainly a good thing. I had personally forgotten all about the issue until I came across this blog post. And it completely changed my feelings about him. It’s really great to see that a lot of people do change when they get a chance to sit back and reflect  on the stupid things they’ve done. Everybody should get a second chance if they want it, even a guy like Zed Shaw if he comes to realize some day that he’s being an asshole.

Well done, Matt. Looking forward to following your work in the future.

For a while now I’ve been working on a Danish forum for Ruby and Rails developers: railsforum.dk. It will be based on the excellent El Dorado “full-stack community web application” by Trevor Turk.

However, I wanted the forum to be in Danish, including menus, system messages etc. Not because Danish Ruby developers don’t understand English, but because I want to emphasize that this is a Danish site for Danish developers.

So I decided to contribute a Danish localization to El Dorado. Quite a work-intensive (read: boring) taks, although it was made a lot easier by another contribution: An almost complete German translation made by a guy called Manfred. So I didn’t have to go through the really boring process of finding all the strings that need to be localized.

Along the way I added a few more features:

  • The option to hide the title and tagline, making the entire header image a link to the front page.
  • A feature to disable tabs on the site. I need this because I want to keep railsforum.dk as simple as possible, and El Dorado has lots of features.
  • Ruby syntax highlighting (incomplete, not yet submitted).

Finally, I rearranged a few items on the front page and added a new “portlet” there after discussing this with Trevor.

Here’s how it looks right now:

Ah yes, and then I had to spend some time untangling my Git repository. Because I am (or was?) such a Git newbie, I had put all my stuff on one branch, making it impossible for Trevor to merge.

It feels really good finally to have made a more significant constribution to an OSS project than the occasional patch or bug report. This has definitely whet my appetite for getting more involved into projects like El Dorado. Also, Github is really an excellent platform for this kind of collaboration – the catchphrase “Social Coding” is spot on.

Follow

Get every new post delivered to your Inbox.