Instiki: add an auto redirect to the default web

March 4th, 2010

I have a few Instiki instances out there: wiki.grassrootsmapping.org and wiki.cartagen.org – and the Grassroots Mapping wiki now has two ‘webs’. Initially when I added a second web, the front page at wiki.grassrootsmapping.org began showing a list of webs instead of the HomePage of the main web… if you’re an Instiki user you’ll know what I’m talking about. You can see the page I saw here: wiki.grassrootsmapping.org/web_list

Instiki allows you to define a DEFAULT_WEB in your /config/environment.rb, but it won’t redirect the web root to that web’s HomePage, which would seem to be the point. Darn. So I forked and patched Instiki on Github, adding the following code to replace line 26 of /app/controllers/wiki_controller.rb:

      if defined? DEFAULT_WEB
        @web_name = DEFAULT_WEB
        redirect_home
      else
        redirect_to :action => 'web_list'
      end

Now if I go to wiki.grassrootsmapping.org, I see the HomePage of my default web. Hooray!

Update: OK, my bad. This is unnecessary:

As distler pointed out on Github, defining DEFAULT_WEB should work out of the box. Why didn’t it work for me, I wondered?

Well, I put the line:

DEFAULT_WEB = 'wiki'

in environment.rb, but I put it OUTSIDE the Rails::Initializer.run do |config| block. Putting that line inside that code block solved my problem.

I’m leaving this all up for future generations to learn from my mistakes. (Most likely me in a year or so.)

Cartagen is now on Github

February 20th, 2010

http://github.com/jywarren/cartagen

Finally.

Tidying up Cartagen a bit with tips from dev.opera.com

January 31st, 2010

dev.opera.com has a great series of tips for improving JavaScript performance. Example:

Use strings accumulator-style

String concatenation can be an expensive process. Using the “+” operator does not wait for the result to be assigned to a variable. Instead, it creates a new string in memory, assigns its result to that string, and it is that new string that may be assigned to a variable. The following code shows a common assignment of a concatenated string:

“a += ‘x’ + ‘y’;”

That code would be evaluated by firstly creating a temporary string in memory, assigning the concatenated value of ‘xy’, then concatenating that with the current value of “a”, and finally assigning the resulting value of that to “a”. The following code uses two separate commands, but because it assigns directly to “a” each time, the temporary string is not used. The resulting code is around 20% faster in many current browsers, and potentially requires less memory, as it does not need to temporarily store the concatenated string:

a += ‘x’;
a += ‘y’;

Fixing Cache Images plugin in Wordpress on MediaTemple

January 24th, 2010

Matt Mullenweg’s great Cache Images plugin for WordPress (Just go to the Plugins > Add New page in your WordPress install and search for it) lets you copy any hotlinked images on your blog into your own /uploads/ folder for safekeeping (and to be polite to others’ servers!), and I love it. But when you first install it, it often chokes, especially on MediaTemple. I’ve had problems with this more than once, so I thought I’d jot this down for future reference and to help anyone else struggling with the same issues. The two problems are a) permissions for the /uploads/ folder, and b) the file_get_contents() function. Here’s a fix:

First, you have to change the uploads directory from a long absolute path to just a relative one, so in Settings > Miscellaneous, instead of:

/bla/bla/mediatemples/long/url/domainname/html/wp-content/uploads/

it should say:

wp-content/uploads

Second, you have to change the file_get_contents() call on line 118 of the plugin file “plugins/cache-images/cache-images.php”. MediaTemple and other hosts don’t like that. But you can usually use the curl() library, so if you add the following code somewhere near the top of the file, you can use this fancy new ‘file_get_contents_curl()‘ function instead of the native one:

function file_get_contents_curl($url) {
	$ch = curl_init();

	curl_setopt($ch, CURLOPT_HEADER, 0);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //Set curl to return the data instead of printing it to the browser.
	curl_setopt($ch, CURLOPT_URL, $url);

	$data = curl_exec($ch);
	curl_close($ch);

	return $data;
}

Then all you have to do is change the call (on what USED TO BE line 118) to:

$img      = file_get_contents_curl( $b['scheme'] . '://' . $b['host'] . str_replace(' ', '%20', $b['path']) . $b['query'] );

That is, just change “file_get_contents” to “file_get_contents_curl()”.

I’d do it myself for you and host the file, but it’s not my code. Hmm, can I commit this change anywhere? Matt?

RAGI on Rails 2.3+

October 28th, 2009

RAGI, a Ruby interface for Asterisk, allows you to handle phone calls with a Ruby on Rails application. The config/environment.rb entry has to be modified a bit for a modern Rails, since many online tutorials/resources were written in the Rails ~1.2 era, and assume WEBrick as the server.

The offending line is this:

class SimpleThreadServer < WEBrick::SimpleServer

Which can be modified to:

class SimpleThreadServer < Mongrel::HttpHandler

The complete configuration you'll need to add inside your Rails::Initializer.run do |config| block is:

  # The following code tells Rails to start a Ragi server
  # as a separate thread.
  ActiveSupport::Dependencies.mechanism = :require
  # Include your application configuration below
  # Simple server that spawns a new thread for the server
  class SimpleThreadServer < Mongrel::HttpHandler
    def SimpleThreadServer.start(&block)
      Thread.new do block.call
      end
    end
  end
  require 'ragi/call_server'
  RAGI::CallServer.new( :ServerType => SimpleThreadServer )

Installing Java 1.4.x on Snow Leopard

October 10th, 2009

OneSwarm’s wiki (link) covers some easy steps for installing Java 1.4 on Snow Leopard. I needed it to get the MPowerPlayer SDK running so I could compile some code for Java-enabled mobile phones. Thanks to wheremydogs.at for pointing out that MPowerPlayer relies on some Java 1.4 classes.

cd /tmp/
wget http://www.cs.washington.edu/homes/isdal/snow_leopard_workaround/java.1.4.2-leopard.tar.gz
tar -xvzf java.1.4.2-leopard.tar.gz
sudo mv 1.4.2 /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2-leopard
cd /System/Library/Frameworks/JavaVM.framework/Versions/
sudo ln -s 1.4.2-leopard 1.4
open "/Applications/Utilities/Java Preferences.app"

For those of you also working with MPowerPlayer, the error I was getting is:

  $ ant
  Buildfile: build.xml

  compile:

  preverify:
       [exec] Error preverifying class java.lang.Class
       [exec]     VERIFIER ERROR java/lang/Class.newInstance0()Ljava/lang/Object;:
       [exec] Illegal type in constant pool
       [exec] Result: 1

  package:

  BUILD SUCCESSFUL
  Total time: 1 second

But now that I have Java 1.4, it’s compiling fine.

Get Rails working again after installing MacPorts

October 9th, 2009

Mac Rails developers: I installed MacPorts to get RMagick, and it installed a new version of Ruby, without RubyGems. This meant that when I typed script/server, it claimed that:

“Rails requires RubyGems >= . Please install RubyGems and try again: http://rubygems.rubyforge.org”

MacPorts had added some crap to my PATH variable. If you edit your ~/.profile you’ll see this line:

export PATH=/opt/local/bin:/opt/local/sbin:$PATH

Just change that to:

export PATH=$PATH:/opt/local/bin:/opt/local/sbin

Then open a NEW shell prompt, i.e. a new Terminal window (this reloads the PATH variable)…

…and it’ll find your OLD version of Rails before the new MacPorts one, and things will work normally. You can confirm by typing “which ruby” in the terminal, and you should see “/usr/bin/ruby” NOT “/opt/local/bin/ruby”.

Amazon s3 storage search interface

October 7th, 2009

I use Amazon S3 for backup, and find that it’s hard to use because there’s no search function, so I can’t see what I’ve backed up.

So, I extended s3cmd.rb (comes with the WONDERFUL s3cmd.rb rsync clone for Amazon S3) with a search command.

Now I can use s3sync.rb to rsync my files up, then type:

s3sync.rb search bucket_name:path/to/restrict/search search_term

and I get, for example:

backup/2009/spatial/jeff-spatial-vertical.key
backup/2009/spatial/spatial-assignment-1-jeff.pdf
backup/2009/spatial/spatial-assignment-1.key
backup/2009/spatial/spatial-assignment-1.key.zip
backup/2009/spatial/spatial-interface
backup/2009/spatial/spatial-lecture-1
backup/2009/spatial/spatial-lecture-1.key
backup/2009/spatial/spatial-lecture-1.key.zip
backup/2009/spatial/spatial-lecture-1/spatial-lecture-1.key
backup/2009/spatial/spatial-lecture-1/spatial-lecture-1.pdf
backup/2009/spatial/spatial-lecture-3.key
backup/2009/spatial/spatial-lecture-3.mov
backup/2009/spatial/spatial-lecture-3.pdf
backup/2009/spatial/spatial-uploads
backup/2009/spatial/spatial-wayfinding.key
you just spent 6.0e-05 cents

The last line is because the price of making a list request in s3 is $0.01 per 1000 requests in the US; so I thought it’d be a good idea to tell people how much they’re spending.

I’ll try to commit this to the main s3sync.net codebase, but for now you can just download it here: s3sync

Composition of a typical OpenStreetMap API response

October 1st, 2009

I’ve been wondering how much of the data transferred by the OpenStreetMap API is actual geometric data as opposed to timestamp and author data. I ran some rough numbers on a typical API response (in JSON, not XML, though these are relative measurements, so it shouldn’t matter too much). The file I examined is here: dr5ru0.json but my count is by number of characters and I did include formatting.

osm-composition

Native JSON parsing… hooray, with benchmarks!

September 27th, 2009

I just tested the native JSON parser in Safari (this is also implemented in Firefox now, and IE8) and it dramatically speeds up the parsing of Cartagen’s JSON data files! Take a look at these times for parsing six typical data plots in milliseconds:

prototype.js’s .evalJSON():
parsed: 43
parsed: 7
parsed: 47
parsed: 63
parsed: 37
parsed: 53
Native JSON.parse():
parsed: 8
parsed: 6
parsed: 6
parsed: 9
parsed: 5
parsed: 7

That’s a sixfold improvement!

And for Firefox 3.5:

prototype.js’s .evalJSON():
parsed: 174
parsed: 157
parsed: 198
parsed: 349
parsed: 155
parsed: 455
parsed: 323
parsed: 276
parsed: 272
Native JSON.parse():
parsed: 13
parsed: 13
parsed: 14
parsed: 20
parsed: 12
parsed: 25
parsed: 20
parsed: 18
parsed: 18

That’s more than 15 times the speed!