Easterbrook on GPL, Presages AltLaw

While playing with my current all-consuming project, AltLaw.org, I came across this case: Wallace v. IBM. In 2006 a man named Daniel Wallace sued various distributors of GNU/Linux, including IBM, Red Hat, and Novell, for “price-fixing.” Since the GPL ensures Linux will always be free, Wallace argued, he cannot afford to enter the market with his own operating system, thus Linux distributors have an illegal monopoly. Judge Frank Easterbrook, in an opinion that mentions Open Office and GIMP, denies the claim, concluding “The GPL and open-source software have nothing to fear from the antitrust laws.”

Easterbrook also mentions the popularity of commercial legal databases such as WestLaw and Lexis-Nexis, “even though courts give away their work (this opinion, for example, is not covered by copyright and may be downloaded from the court’s web site and copied without charge).”

Brilliant! Easterbrook captures both AltLaw’s reason for existence and its methodology in one sentence. Couldn’t have said it better myself, Frank.

Parsing Complex Comparisons

An interesting tidbit: can your programming language parse a < b < c? Perl can’t. Ruby can, but returns an error “undefined method `>’ for false:FalseClass.” Interestingly, Python accepts it, and even gives the correct result. Something clever must be going on in the parser to make that work.

Update October 17: Although Lisp can’t parse the expression directly, it does correctly handle the equivalent S-expression (< a b c).

Why Doesn’t My Rails App Use memcached with cached_model?

Answer: you’re using the latest version of Rails (1.2.3), which slightly changes the syntax of its SQL statements. cached_model relies on a regular expression to match that SQL statement.

To fix: Dive into the source of the cached_model gem, find the file lib/cached_model.rb, and change the first line after def self.find_by_sql to this:

    return super unless args.first =~ /^SELECT \* FROM #{table_name} WHERE \(#{table_name}\.`?#{primary_key}`? = '?(\d+)'?\) *(?:LIMIT 1)?/

And it works!

Get Apache Serving Static Files With Prefixed Mongrel

I decided to run AltLaw.org under a “/v1” URL prefix. It’s still beta, and the URL structure will likely change in the future. I don’t want to break 160,000 links when that day comes. Fortunately, Mongrel makes this pretty easy with the –prefix option to mongrel_rails.

I added --prefix '/v1' to my mongrel_rails command line. After removing absolute URLs (those not using {:controller=>...}) from my views, everything worked great.

The only problem is, this technique prevents Apache from serving static files without hitting the Mongrel server. A typical mod_rewrite directive like this:

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f
RewriteRule (.*) $1 [L]

doesn’t work, because the REQUEST_URIs now all start with “/v1” and the files in “MyRailsApp/public” don’t.

Here’s a simple workaround: make a symlink like this:

cd /path/to/MyRailsApp/public
ln -s . v1

That’s right, “v1” is a symlink that points back to the “public” directory. I was afraid this might cause an infinite loop, but it doesn’t. Keeping the same mod_rewrite rule above, Apache will serve the static files under “public” even if the request is prefixed with “/v1”. Pretty cool.

Darcs with Capistrano for Rails

I’ve used Darcs as my only version-control system for a while now. When I got into Rails, I naturally wanted to use Capistrano. Unfortunately, Darcs and Capistrano don’t get along too well. Darcs’ file-based repositories don’t mesh well with Capistrano’s assumption that the repository is accessed through a server, a la Subversion.

I ran into problems with cap deploy:update_code because Darcs couldn’t find the repository. After a discussion on the Capistrano mailing list I decided to go my own route.

I have two Darcs repositories, one on my development machine and one on the server. I darcs push patches from development to the server. Then I have my own custom Capistrano tasks to get the latest code from the server’s copy of the repository. This is adapted from the Capistrano sources:

namespace :deploy do
  task :update_code, :except => { :no_release => true } do
    on_rollback { run "rm -rf #{release_path}; true" }

    run("darcs get --partial /home/myapp/repo --repo-name=#{release_path}")
    run("rm -rf #{release_path}/_darcs")

    finalize_update
  end
end

I also had to write a custom finalize_update task to add the links to the shared Rails directories:

namespace :deploy do
  task :finalize_update, :except => { :no_release => true } do
    run <<-CMD
      ln -s #{shared_path}/log   #{latest_release}/log &&
      ln -s #{shared_path}/tmp   #{latest_release}/tmp &&
      ln -s #{shared_path}/data  #{latest_release}/data &&
      ln -s #{shared_path}/index #{latest_release}/index &&
      ln -s #{shared_path}/config/database.yml #{latest_release}/config/database.yml &&
      ln -s #{shared_path}/public/system #{latest_release}/public/system
     CMD
  end
end

Apache Proxy for Rails Returns 403 Forbidden

Trying to set up Apache2 as a proxy for mongrel on my new Ruby on Rails server, following the instructions on the mongrel site. I kept getting “403 Forbidden” errors on every request. I found a comment that seemed to describe the same situation. Sure enough, editing /etc/apache2/mods-enabled/proxy.conf to change “Deny” to “Allow” fixed the problem. I kept ProxyRequests turned off, which is supposed to prevent my site from becoming an open proxy, but I’m still nervous about removing that “Deny” directive. I wish there were a more authoritative source of information on this.

Rails Sucks, Long Live Rails

Wowsers. I just spent two nail-biting, hair-pulling days getting Ruby on Rails running on a new dedicated server. What’s the deal here? I spent the first six hours trying to get Capistrano to work with darcs. Then I gave up on Capistrano.

I didn’t know anything about Mongrel, nginx, Lighttpd, or any of that stuff, so I decided to try the simplest setup I could think of: Apache2 with FastCGI. I’d done this on a shared host before, so at least I had some vague idea of what to expect. Some things I learned:

  • Do not use Ubuntu’s rubygems package; build from source. The Ubuntu package has a weird configuration that stores gems under /var, where nothing can find them.
  • Do not use Ubuntu’s fcgi-ruby package. Install the gem (see below).
  • Make sure your web-data user (or whatever user Apache runs as) has write privileges on RAILS_ROOT/log, RAILS_ROOT/tmp, RAILS_ROOT/index (if you’re using Ferret), and RAILS_ROOT/public (if you’re using page caching).
  • Make sure there are no leftover files owned by other users in any of those aforementioned directories.
  • Don’t rely on Apache to provide Rails with environment variables like RAILS_ENV and PATH. Set them in environment.rb.

My conclusion, after I finally got the app running: Rails has major work to do when it comes to startup error reporting. When dispatch.fcgi dies repeatedly without neither output nor log messages, there’s something wrong. Seriously, how hard could it be to dump a plain-text HTTP response with a stack trace? That way I’d at least know why it won’t start, instead of staring at “Rails application failed to start properly” for hours on end.

For the record, here was the installation recipe I came up with. This is on Ubuntu Feisty:

MySQL:
sudo aptitude install mysql-server mysql-client

Memcached:
sudo aptitude install memcached

Basic ruby essentials:
sudo aptitude install ruby libruby1.8-extras irb rdoc ri

Extra ruby libraries:
sudo aptitude install libreadline-ruby libopenssl-ruby libmysql-ruby

Essentials for building native ruby extensions:
sudo aptitude install build-essential ruby1.8-dev libfcgi-dev

The latest version of rubygems (NOT the Ubuntu package):

wget http://rubyforge.org/frs/download.php/20989/rubygems-0.9.4.tgz
tar -xzf rubygems-0.9.4.tgz
cd rubygems-0.9.4
sudo ruby setup.rb

Gems:
sudo gem install --include-dependencies --no-rdoc --no-ri rake rails acts_as_ferret acts_as_taggable asciify BlueCloth builder cached_model chronic feedtools ferret hpricot memcache-client mongrel RedCloth fcgi

Stretching LaTeX

I recently picked up The LaTeX Companion, 2nd Edition. It’s… dense. It shows a lot of amazing things LaTeX can do, but also highlights its weaknesses.

Most of these weaknesses have to do with the legacy of TeX itself. For example, it’s difficult to flow text around objects, because TeX determines line widths before it lays out the page. There’s a package to work around this, but it’s an imperfect hack.

The font encoding schemes are a nightmare. TeX was born in a 7-bit world, so Knuth’s Computer Modern fonts stuck the mathematical and typographic symbols in wherever they fit. Then the Europeans created an 8-bit TeX, before the ISO-8859-* encodings were standardized. To make all this work with new fonts, different people have defined packages to map all the different LaTeX symbols onto, usually, collections of two or three fonts. Standard LaTeX still does not fully support Unicode, although some alternate implementations do.

TeX still produces better-looking output than any other formatting system. But it’s a chore to work with, even for nuts like me who enjoy delving into the technical/mathematical details of typography. The syntax is well-nigh incomprehensible, and the error messages are about as user-friendly as a kernel panic.

I’d love to have TeX as a low-level service to which other applications — word processors, even a web browser — could delegate their text formatting. There is a TeX daemon, but I’m not aware of any desktop applications that use it.