HomeHome ArchiveArchive

MapLayers plugin for Rails

MapLayers map

Update July 31, 2008

The current version is now hosted and documented on github.

Getting Started

Install the latest version of the plugin:

  ./script/plugin install http://www.sourcepole.ch/svn/plugins/map_layers/trunk

Create a controller and a view

  ./script/generate controller Map index

Initialization of the map

Add the map viewer initialization to the index action in the controller:

  @map = MapLayers::Map.new("map") do |map, page|
    page << map.add_layer(MapLayers::GOOGLE)
    page << map.zoom_to_max_extent()

Add this to the head of your view:

  <%= map_layers_includes :google => "ABQIAAAA3HdfrnxFAPWyY-aiJUxmqRTJQa0g3IQ9GZqIMmInSLzwtGDKaBQ0KYLwBEKSM7F9gCevcsIf6WPuIQ" %>

Put a map in the body your view:

  <div id="map" style="width: 512px; height: 256px;"></div>

  <%= @map.to_html %>

Test your basic map with localhost:3000/map

Multiple layers

Add a second layer and some more controls in the controller action:

  @map = MapLayers::Map.new("map") do |map, page|
    page << map.add_layer(MapLayers::GOOGLE)
    page << map.add_layer(MapLayers::YAHOO_HYBRID)

    page << map.add_control(Control::LayerSwitcher.new)
    page << map.add_control(Control::Permalink.new('permalink'))
    page << map.add_control(Control::MousePosition.new)

    page << map.zoom_to_max_extent()

Add the Yahoo Javascript library to the includes:

  <%= map_layers_includes :google => "ABQIAAAA3HdfrnxFAPWyY-aiJUxmqRTJQa0g3IQ9GZqIMmInSLzwtGDKaBQ0KYLwBEKSM7F9gCevcsIf6WPuIQ", :yahoo => "euzuro-openlayers" %>


To include all Javascript APIs, insert your API keys in the following statement:

  <%= map_layers_includes :google => "ABQIAAAA3HdfrnxFAPWyY-aiJUxmqRTJQa0g3IQ9GZqIMmInSLzwtGDKaBQ0KYLwBEKSM7F9gCevcsIf6WPuIQ", :multimap => "metacarta_04", :virtualearth => true, :yahoo => "euzuro-openlayers" %>

Updating the map

Now we want to add some simple markers in an Ajax action. First we add a link in the view:

  <%= link_to_remote "Add marker", :url => { :action => "add_marker" } %>

This requires including the prototype library:

  <%= javascript_include_tag 'prototype' %>

Then we include a marker layer in the map. Put this after the add_map_layer statements in the controller:

  page.assign("markers", Layer::Markers.new('Markers'))
  page << map.addLayer(:markers)

and then we implement the Ajax action:

  def add_marker
    render :update do |page|
      @markers = JsVar.new('markers')
      page << @markers.add_marker(OpenLayers::Marker.new(OpenLayers::LonLat.new(rand*50,rand*50)))

For accessing the marker layer in the Ajax action, we declare a Javascript variable with page.assign and access the variable later with the JsVar wrapper.

Publish your own data

Create a model:

  ./script/generate model --skip-timestamps --skip-fixture Place placeName:string countryCode:string postalCode:string lat:float lng:float
  rake db:migrate

Import some places:

  ./script/runner "Geonames::Postalcode.search('Sidney').each { |pc| Place.create(pc.attributes.slice('placeName', 'postalCode', 'countryCode', 'lat', 'lng')) }"

Add a new controller with a map_layer:

  class PlacesController < ApplicationController

    map_layer :place, :text => :placeName


And add a layer to the map:

  page << map.addLayer(Layer::GeoRSS.new("GeoRSS", "/places/georss"))

Other types of served layers:

  page << map.add_layer(Layer::GML.new("Places KML", "/places/kml", {:format=> JsExpr.new("OpenLayers.Format.KML")}))

  page << map.add_layer(Layer::WFS.new("Places WFS", "/places/wfs", {:typename => "places"}, {:featureClass => JsExpr.new("OpenLayers.Feature.WFS")}))

Spatial database support

Using a spatial database requires GeoRuby and the Spatial Adapter for Rails:

  sudo gem install georuby
  ruby script/plugin install svn://rubyforge.org/var/svn/georuby/SpatialAdapter/trunk/spatial_adapter

Install spatial functions in your DB (e.g. Postgis 8.1):

  createlang plpgsql $DB
  psql -d $DB -q -f /usr/share/postgresql-8.1-postgis/lwpostgis.sql

Create a model:

  ./script/generate model --skip-timestamps --skip-fixture WeatherStation name:string geom:point
  rake db:migrate

Import some station:

  ./script/runner "Geonames::Weather.weather(:north => 44.1, :south => -9.9, :east => -22.4, :west => 55.2).each { |st| WeatherStation.create(:name => st.stationName, :geom => Point.from_x_y(st.lng, st.lat)) }"

Add a new controller with a map_layer:

  class WeatherStationsController < ApplicationController

    map_layer :weater_stations, :geometry => :geom


And add a WFS layer to the map:

  page << map.add_layer(Layer::WFS.new("Weather Stations", "/weather_stations/wfs", {:typename => "weather_stations"}, {:featureClass => JsExpr.new("OpenLayers.Feature.WFS")}))


The MapLayers plugin for Rails is released under the MIT license.


For any questions, enhancement proposals, bug notifications or corrections visit rubyforge.org/projects/map-layers or send a mail to

pka at sourcepole.ch

Copyright (c) 2008 Pirmin Kalberer, Sourcepole AG

A graphical boot from BIOS to your Application


This article describes how to configure your Linux system to display an nice graphical image from the BIOS until your application or the login manager appear. No text should appear on the screen during that time.

The web is full with descriptions and tools that cover tiny parts of this process, however there seems to be no document that covers the whole path end to end. This document wants to do this and cover the whole stretch.

Please write to me if you have informations that complement or complete this article. You find my email at the bottom.


Linux’ boot process consists of multiple parts, that each start the next part

  1. the BIOS boots
  2. the boot loader gets loaded
  3. the kernel starts
  4. init start
  5. the rest of the userspace processes get started
  6. X starts

We now look at each of the points separately.

the BIOS boots

Normally you can not do much about the BIOS displaying its chatter. Some BIOSes support displaying a custom image, however that’s something you’ll need to find out through reading the technical documentation of your mainboard or BIOS.

the boot loader gets loaded

I’ll only cover here GRUB, since it seems to be the dominant boot loader today.

On an average system GRUB takes ony a second or so to load itself and the kernel. Since this is so short a time I am ignoring it and accepting a “black” screen during that second.

This effect can be achieved by setting timeout = 0 in /boot/grub/menu.lst. This will make GRUB skip displaying the boot menu and directly load the default boot entry. If you need to select a different entry then you’ll have to press cursor down in the split second between the BIOS and before GRUB is loaded.

GRUB will still display a line saying that it is loading the kernel (and if your system is configured accordingly also the init filesystem), as described above that line is visible only for a very short time and thus I am ignoring that here:

Uncompressing Linux... Ok, booting the kernel.

However if you want to remove even that, there is a patch from Ubuntu that seems to do that (I have not tested it): quiet.diff

the kernel starts

GRUB loads the kernel and possibly an init filesystem (named initrd or initramfs in Linux speak). It starts the kernel and if configured accordingly on your system, passes the init filesystem on to the kernel.

You can tell the kernel to display an image as soon as it is started. This is usually referred to as “the frambuffer boot logo”. A howto can be found here.

After displaying the boot logo, the linux kernel will usually proceed with verbosely initializing all the hardware. You can suppress all the output by specifying quietin the kernel boot parameters. Just add the word quiet to the kernel boot parameters in /boot/grub/menu.lst. Mine looks like this:

title           Linux
root            (hd0,0)
kernel          /boot/vmlinuz- root=/dev/hda1 ro vga=791 quiet splash

init start

After the kernel has started it will either mount and continue with the boot procedure inside the init filesystem (initrd or initramfs) or it will start the init process.

Both the init filesystem and the init process will immediately start babbling aloud about what they are doing.

What we need to achieve at this stage is:

  1. if that applies to make sure that whatever is started in the init filesystem is shut up
  2. to shut up init
  3. to shut up all that follows the first started processes

I will not go into siliencing the init filesystem, since I am not using any but instead made a custom built kernel, that has all the minimally required drivers compiled into it and thus am not qualified to comprehensively cover the init filesystem part.

The init process itself will dump one line where it will identify itself:

INIT: version 2.68 booting

I don’t know how to prevent init from writing that. Patching it out from the source should be easy, however there should be a better way.

the rest of the userspace processes get started

After init and/or the init filesystem are started, they will usually proceed with mounting all the required filesystems and dispatching udev which will try to identify all hardware, load the required drivers/kernel modules and allocate the according device node in /dev.

This will produce another 3 or so lines. It should be easy to disable displaying those by patching the respective init scripts, however there should be some universal and standard way to do that, which I do not know of.

After that, but as soon as possible you can start a userspace splash manager. I’m using splashy, there are numerous others though.

X start

At some final point your application or the login manager will start as an X client. I am doing that like this:

/etc/init.d/splashy stop
xinit /usr/bin/my_app

however there are numerous other ways to achieve this. The point is that you need to stop the splash screen manger before your target application or the login manager is started.

One final ugly unsolved problem is the unaesthetic start procedure of the X server, which will typically first display the infamous classic “X” as the background. One can use xsetroot to set the background once X is loaded however between the start of X and the execution of xsetroot you’ll still be looking at “X”’s default background. Again, there should be a way to initialize the background before X switches into graphics mode with a nice background, which I have not found yet.

Contributions to this HOWTO are gladly accepted, thanks, Tomas Pospisek, tpo_deb at sourcepole.ch.

Note that http://sourcepole.com is doing develpment of embedded Linux systems and will gladly provide consulting and implementation to solve any of the above mentioned or further problems.

Nginx kills large SVN commits

Lately, when committing large files with Subversion I had problems like this:

\$ svn commit linux-
Adding (bin) linux-
Transmitting file data .svn: Commit failed (details follow):
svn: PUT of '/svn/!svn/wrk/38f59907-4ccf-4e05-acf4-444499e715cc/embipc/branches/ipc/linux-image/linux-': Could not send request body: connection was closed by server. (<https://www.example.org>)
svn: Your commit message was left in a temporary file:
svn: '/some/path/embipc/branches/ipc/linux-image/svn-commit.tmp'

Apache’s Log was very quiet about the problem. All I could see that SVN would be deleting the uploaded file after abort (that’s what I think it was doing): - joe [07/Mar/2008:13:53:59 +0100] "DELETE /svn/!svn/act/38f59907-4ccf-4e05-acf4-444
3b969 HTTP/1.0" 204 - "-" "SVN/1.4.4 (r25188) neon/0.26.4"

The root of the problem is however that we’re having multiple virtual servers on our hardware and are proxying and distributing request to them through nginx. And nginx had a default setting for maximal file upload sizes, which made it automatically abort all commits that exeeded that size:

2008/03/07 13:56:16 [error] 15916\#0: \*1463829 client intented to send too large body: 59042053 bytes
, client:, server: www.example.org, URL: "/svn/!svn/wrk/38f59907-4ccf-4e05-acf4-444

We had to change the respective setting in nginx.conf, and everything was fine after:

 \# ---- dev ---
 location /svn {

      # Set the max size for file uploads
      client_max_body_size 100M;

The real problem here is though, that the stack of technologies is not able to pass forward errors. It’s the svn client that should have told me “client intented to send too large body: 59042053 bytes” and not the nginx log.

Taxme 2006 auf Debian lenny (testing)

  • Damit Taxme 2006 funktioniert, musste ich Blackdown’s j2re1.4 installieren, man bekommt es hier. Einfach

    deb http://sunsite.cnlab-switch.ch/ftp/mirror/java-linux/debian testing non-free

    in /etc/apt/sources.list eintragen. Offenbar ist Taxme nicht kompatibel mit 1.5er oder 1.6er JRE’s.

  • Damit die Hilfe im Taxme 2006 erscheint, musste ich:
    • das Paket libxul0d installieren (welches /usr/lib/xulrunner/libgtkembedmoz.so enthält, welches Taxme benötigt)
    • das folgende Startscript schreiben:

      # offenbar braucht SWT libgtkembedmoz, welches
      # TaxMe2006: z.B. in libxul0d in /usr/lib/xulrunner/ liegt
      #            siehe http://www.aptana.com/docs/index.php/Installing_Aptana_Milestone_7_on_Linux#Other_Linux_Distributions
      #                  http://dev.eclipse.org/newslists/news.eclipse.platform.swt/msg22648.html
      export MOZILLA_FIVE_HOME=
      export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/lib/xulrunner/
      cd TaxMeBe2006
    • Das Problem ist nur, dass zwar die Hilfe erscheint, der Index sichtbar ist, aber, wie weiter unten bei der Kurzhilfe der Hilfetext selbst leer bleibt. Tips?
  • Die Kurzhilfe scheint nicht zu funktionieren. Tips?