Geokit 1.2: Gem + Rails plugin, Rails 2.2.2 ready

Dec 21 by Andre in GeoKit »

Geokit gets some love!

  • Gem released: Geokit is now separated into a Gem (geokit-gem) and a Rails plugin (geokit-rails). You can use the gem separately. The plugin requires the gem.
  • Rails 2.2.2 compatible: the plugin is all updated for Rails 2.2.2
  • Many bug fixes/updates:
    • Improved Geocoder.us support -- respects authentication, and can geocode city names or zipcodes alone
    • cross-meridian finds work correctly with bounds conditions
    • fixed a problem with columns with "distance" in their name
    • added Geonames geocoder
    • the gem and plugin are now hosted at Github. The overall site is still athttp://geokit.rubyforge.org

Geokit makes it easy to build location-based apps. It provides geocoding, location finders, and distance calculation in an easy-to-use API.

Building a simple Sinatra/DataMapper/HAML/SASS + Passenger app

Dec 18 by Andre in Sinatra »

Sinatra is really fun to work with. It's small and fast. It doesn't make many assumptions. If something goes wrong, it's pretty easy to go into the source and figure out what is going on.

There were a couple projects I wanted to take for a spin: Sinatra, Datamapper, HAML, and SASS. I decided to roll them all up into one proof-of-concept project. I don't go into a lot of depth on each, just enough to know that I can get it all up and running.

Also, since I'm running Passenger on some production boxes now, I wanted to deploy my Sinatra/Datamapper app through Passenger's Rack support.

How I organized my Sinatra App

Sinatra doesn't care how you organize your application. You can put everything in one file, or start to break things out into a Rails-ish directory structure. Of course, if you break things out into separate files, you'll need to require files as necessary -- Sinatra doesn't have conventions like Rails does about where to find things.

I put everything except for views in one file. So configurations, models, and actions all went in main.rb. My directory structure looks like this:

/app
  main.rb
  /views
    index.haml
    layout.haml
    style.sass
/config
  deploy.rb
/public
Capfile
Rakefile
config.ru

The /app and /views directories might be overkill for a simple app like this. Coming from Rails, it was easy to lay things out like this since it's instantly recognizable to me.

My main application file

My proof-of-concept app is a simple to-do list. It has one model, Todo. Basically, I just needed a testing ground for a DataMapper model.

# main.rb
require 'rubygems'
require 'sinatra'
require 'dm-core'
require 'dm-validations'
require 'logger'


## CONFIGURATION
configure :development do
  DataMapper.setup(:default, {
    :adapter  => 'mysql',
    :host     => 'localhost',
    :username => 'root' ,
    :password => '',
    :database => 'sinatra_development'})  

  DataMapper::Logger.new(STDOUT, :debug)
end

configure :production do
  DataMapper.setup(:default, {
    :adapter  => 'mysql',
    :host     => 'localhost',
    :username => 'user' ,
    :password => 'pass',
    :database => 'sinatra_production'})  
end

### MODELS
class Todo
  include DataMapper::Resource
  property :id,         Integer, :serial=>true
  property :title,      String
  property :created_at, DateTime
  property :complete,   Boolean, :default=>false

  validates_present :title
end

### CONTROLLER ACTIONS

# index
get '/' do
  @todos=Todo.all :order=>[:created_at]
  haml :index
end

# create
post '/' do
  todo=Todo.create(:title=>params[:title],:created_at=>Time.now)
  redirect '/'
end

# mark complete / incomplete
get '/:id/mark/:is_complete' do
  todo=Todo.get(params[:id])
  todo.update_attributes(:complete=>(params[:is_complete]=='complete'))
  redirect '/'
end

get '/:id/delete' do
  todo=Todo.get(params[:id]).destroy
  redirect '/'
end

# SASS stylesheet
get '/stylesheets/style.css' do
  header 'Content-Type' => 'text/css; charset=utf-8'
  sass :style
end

Notes on this: * for my purposes, it was enough to just log DataMapper to Standard out in development (that's the DataMapper::Logger.new(STDOUT, :debug) line). A more robust solution would be to figure out how use Rack's logging mechanism. * note that I passed symbols to my configure blocks. If you use symbols to represent your environment, make sure you set your environment to a symbol as well. See the config.ru file below.

My config.ru

require 'rubygems'
require 'sinatra.rb'

# Sinatra defines #set at the top level as a way to set application configuration
set :views, File.join(File.dirname(__FILE__), 'app','views')
set :run, false
set :env, (ENV['RACK_ENV'] ? ENV['RACK_ENV'].to_sym : :development)

require 'app/main'  
run Sinatra.application

Some notes here: * Sinatra defines #set at the top level as a way to set application configuration. You'll see alternate ways to specify configuration, like providing multiple values in a hash, or even setting the Sinatra::defaultoptions hash directly. * the set :env converts ENV['RACKENV'] to a symbol -- that's so it will match the symbol passed to the configure block in main.rb

Notes on Rake

Within Rails, Rake includes everything in lib/tasks with a glob ... there's nothing hard and fast about this, it's just a Rails convention. I put my one task in Rakefile itself, but if you had more, you could easily decide where you wanted your blah.task files, and include them from Rakefile just like Rails does.

My one rake task rebuilt my schema from my DM model definition. Note this is destructive -- it blows away all the data in your table whenever you run it.

task :migrate do
  DataMapper.auto_migrate!
end

Notes on Capistrano

I wanted to do a simple upload to my production server, with no SCM involved. It turns out Capistrano makes that easy. In deploy.rb, just do:

# simple upload -- no scm involved
set :repository, "."
set :scm, :none
set :deploy_via, :copy

Cap will zip everything up, scp to your server, and do its usual symlinking etc. Very nice for quick proof-of-concepts!

Like Rake, Capistrano for Rails is driven by "load" directives within Capfile. This is where the "Rails" conventions are bootstrapped:

Dir['vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) } # this loads anything from your installed your plugins
load 'config/deploy' # this is your actual deploy.rb # it uses all that stuff in the gem's deploy.rb

My View, Layout, and stylesheet

app/views/index.haml

#new-todo
  %form{:method => "post"}
    %input{:type=>'text', :size=>40, :name=>'title', :id=>'todo-title'}
    %input{:type=>'submit', :value=>'New Todo'}

#content
  %p== #{@todos.size} Todos
  %table.display
    %thead
      %th{:width=>'80%'} Title
      %th Controls
    - @todos.each do |todo|
      %tr{:class=>("complete" if todo.complete)}
        %td{:class=>'title'}= todo.title
        %td
          %a{:href=>(todo.complete ? "#{todo.id}/mark/incomplete" : "#{todo.id}/mark/complete" )}= todo.complete ? "reopen" : "mark complete"
          |
          %a{:href=>("#{todo.id}/delete" )}= "delete"

%script
  :plain
    document.getElementById('todo-title').focus();

app/views/layout.hml

!!!
%html
  %head
    %title Todo
    %link{:rel=>'stylesheet', :href=>'/stylesheets/style.css', :type => "text/css"}       
  %body
    #banner My To Do List
    = yield

app/views/style.sass

.complete
  :background #eee
  .title
    :text-decoration line-through
table.display
  :border-collapse collapse
  :width 100%
  td
    :border 1px solid gray
    :padding 4px
#new-todo
  :background #eee
  :padding 10px
  input
    :font-size 18px
body 
  :font-family arial
  :padding 0px
  :margin 0px
#content 
  :padding 10px
#banner
  :height 50px
  :border-bottom 2px solid #777
  :background #aab
  :text-align center
  :font-size 24px

What I learned ... how to:

  • create a simple web app in Sinatra
  • use DataMapper for an ORM
  • use HAML and SASS
  • run my app in development and production environments (production on Passenger)
  • deploy quick-and-easy without an SCM using capistrano's scp capability

Vote for Hotspotr @ Industry Standard

Aug 06 by Andre in Wifi Cafes »

vote for hotspotr

Hotspotr, my community-driven hotspot finder, is a finalist in the Industry Standard Innovation 100 Awards in the Lifestyle category. It's up against some stiff competition from well-known sites. Help us out by voting for Hotspotr!

From the Industry Standard:

We're now at the voting stage, which is also decided by the community. The more votes you get, the more likely you'll become a winner in one of the ten categories. Voting will run from now (August 4th) through October 3, 2008.

Go here to vote for Hotspotr: http://www.thestandard.com/awards/tis100/show_category/5741

Railsconf Bound

May 29 by Andre in Railsconf »

Heading up this afternoon. This year looks great, lots of sessions and BOFs look interesting, and of course it's great catching up with folks from all over. I'll be at the Advanced Rails Recipes Book Signing Friday during lunch rubbing elbows with the other Recipe authors -- stop by and say hi!

Development with Rails + Passenger (AKA mod_rails) on Mac

May 24 by Andre in Ruby on Rails »

Passenger, AKA mod_rails

There are a number of posts (one, two) out there on getting Phusion's Passenger up and running on OSX (Leopard). I decided to give it a go, and was pleased to discover several things:

  1. Despite reports to the contrary, Passenger installed just fine with Leopard's built-in Apache (I'm running Apache 2.2.8).
  2. Setup is very easy, as advertised.
  3. My default doc root(~/Sites) is works exactly as it did before. I do some HTML and PHP work there, so it was key that it continue to work properly.

Since the install process itself is quite easy, I wanted to offer a few tips for utilizing Passenger in a typical dev environment -- i.e., what you need after you get your first Passenger-powered Rails app up and running.

Your Brain on Passenger

As you know, script/server starts your Rails app on a specific port. If you bounce around between a number of applications at any one time, you're probably used to either starting them on different ports, or control-c'ing your current mongrel, cd'ing to another app's directory, and script/server'ing again. This familiar pattern changes when you're running passenger. All your apps are available at any one time, as long as you have your vhosts configured.

If you're like me, you usually hit your currently running Rails app on http://localhost:3000. That also changes when you're running Passenger. Instead, you'll hit a unique URL for each app, which you've configured in /etc/hosts to just go to 127.0.0.1

Setting up a new app

I set up a lot of Rails apps in my dev environment. With Passenger, in exchange for the on-demand convenience of accessing any of your apps any time, there are a few additional setup steps to take whenever you introduce a new app into your dev environment.

  1. create your rails project as usual
  2. add a new vhost. I configure mine in /private/etc/apache2/extra/http-vhosts.conf
  3. add the host in /etc/hosts
  4. restart apache: sudo apachectl restart

Here's a vhosts example with two apps I'm running locally. You can set up as many apps as you want this way:

  <VirtualHost *:80>
    DocumentRoot "/Users/andre/projects/rails/hotspotr/public"
    ServerName dev.hotspotr.com
    ErrorLog "/Users/andre/projects/rails/hotspotr/log/error.log"
  </VirtualHost>

  <VirtualHost *:80>
    DocumentRoot "/Users/andre/projects/rails/shapewiki/public"
    ServerName dev.shapewiki.com
    ErrorLog "/Users/andre/projects/rails/shapewiki/log/error.log"
  </VirtualHost>

Two things to note here:

  1. The ErrorLog line is optional. If you don't include it, the error output for this app will go to /private/var/log/apache2/error.log. Not that that's bad, but you're probably not used to looking for Rails logs there.
  2. I decided to go with the convention of dev.[PRODUCTION_URL].com. You can use anything here, as long as it matches up with an entry in /etc/hosts (see below)

And here's an example /etc/hosts addition to match the two virtual hosts above:

  127.0.0.1       dev.hotspotr.com
  127.0.0.1       dev.shapewiki.com

That's it! Go to (for example) http://dev.hotspotr.com, and you're hitting you local development app. There is nothing to start and stop. The first request for any app you hit will take a moment. Subsequent requests will feel quite snappy.

Let's Set up some Aliases to Make it all Flow

Here are the aliases I added to my .bashrc file to give me quick access to everything I needed for a new, Passenger-centric workflow in my development environment:

# Use this in any RAILS_ROOT dir. That restart.txt file tells mod_rails to restart this app.
# You'll want to do this when (for example) you install a new plugin.
alias restart_rails='touch tmp/restart.txt'

# By default, your app's error log now goes here. Unless you configure your apps otherwise, 
# it's helpful to have an alias to take you to your error log quickly.
alias apache_logs='cd /private/var/log/apache2/'

# You'll be adding to your vhosts configuration everytime you introduce a new Rails app. 
# Might as well make it a shortcut
alias vhosts='sudo vi /private/etc/apache2/extra/httpd-vhosts.conf'

# Dito with hosts
alias hosts='sudo vi /etc/hosts'

# You'll need to restart apache whenever you make a change to vhosts. 
# You can also click System Preference->Sharing->Web Sharing, but this is quicker.
alias apache_restart='sudo apachectl restart'

A Request for NetBeans: faster go-to file

May 22 by Andre in Ruby on Rails »

A small thing, but it impacts every moment spent with code: the speed of the as-you-type file lookup/open. On Netbeans, Control-Shift-O takes several seconds (up to 6 seconds in my experience) with large projects.

In contrast, Aptanta's, equivalent Apple-Shift-R is instantaneous -- it behaves like a direct link from thought to file. It also helps that the default keyboard shortcut rolls off nicely with one hand.

So here's my NetBeans enhancement request for faster go-to file.

Server and Application Monitoring with Scout

Apr 15 by Andre in Ruby on Rails »

Highgroove's Scout is live! Scout is our server monitoring and reporting application. If you didn't have the opportunity to test-drive it during the beta period, you can now sign up for any of the plans. Why? Three reasons, based on my own Scout usage over the last few months:

  • Scout makes you look smart: if something goes wrong with a client's app, I generally know about it before they call me. So I get to be very proactive. In one case I was able to fix a crashed server before the client even realized anything was wrong.

  • Scout helps you build better apps: I had some memory-sucking CSV handling in one of my applications ... but it only happened under certain circumstances in production. With Scout, I was able to correlate the mongrel memory spikes with user activity and zero in on the problem. The result: mongrel instances that don't spike to 200MB, and a better experience for users.

  • Scout helps you sleep better: uncertainty is a stressor, and the more apps you have out there the more things you have to be uncertain about. Just knowing that I'll get an email notification if something goes astray helps my peace of mind a lot. Which means my mind is clear to ... design and build more apps!

Ready to learn more? Here's Derek's official launch post. Or cut to the chase and hit the Scout signup page!

Hotspotr partners with LightPole for mobile

Mar 18 by Andre in Wifi Cafes »

Hotspotr -- my community-driven WiFi hotspot site -- announced a content-providing partnership with LightPole today. You can read the press release over at http://lightpole.net/press/index.html.

Hotspotr lists over 8,000 user-contributed WiFi hotspots. LightPole provides a mobile client you can use to browse Hotspotr from your mobile phone using an interactive, maps-based interface:


You can download the LightPole mobile client for free from the Hotspotr homepage.


Separately, Hotspotr is also taking advantage of the Google Maps streetview functionality. For locations where streetview is available, you will have the option to browse the 3-d streetview imagery:



See an example at the Dolores Park Cafe in San Francisco.

deprec2: Mongrel, nginx, Rails, mysql on Ubuntu 7.1

Feb 26 by Andre in Ruby on Rails »

Following up on my previous post on low-cost staging environments, I chose a host and set up my staging environment.

Note: these are the steps I took to make it work. They are probably not the optimal steps. Actually, I'll go one step further: I guarantee you these are not the optimal steps. But, I did get my staging environment up and running in less then three hours.

1) signed up for SilverRack.

Why? Dave from SilverRack offers $10 off if you're involved in a Ruby user group, which makes the total cost of a 256MB vps $10/mo. Hard to beat that from a pure cost perspective.

  • signup took two minutes including paying my first month on paypal
  • the VPS was provisioned about two minutes after that. I had originally chosen centos, but realized I needed Ubutu 7.1 for deprec 2 -- SilverRack has a simple web-based reinstall you can do yourself, and it took a minute. Note: the Rails stack on CENTOS (before I changed to Ubuntu) looked like it was Rails 1.2 based.

2) install new cap

(I hadn't upgraded to 2 yet)

sudo gem install capistrano -v2.1.0

3) install deprec 2 preview

... I had a hard time finding the gem; grab it from the wiki page like so: curl http://www.deprec.org/attachment/wiki/WikiStart/deprec-1.99.13.gem?format=raw > deprec-preview.gem

sudo gem install deprec-preview.gem

4) decided to create myself a little deprec play area, but I'm not sure it's necessary:

cd ~/projects mkdir deprec cd deprec mkdir config depify .

4.5) set up ssh keys

. . . I know deprec provides some tasks for this, but I just did it manually (copied my local ~/.ssh/id_rsa.pub) into my new vps's ~/.ssh/

5) let's setup a rails stack!

Used an IP because my dns hasn't resolved yet. If your dns has resovled ... good for you!

export HOSTS=xxx.xxx.xxx.xxx 

# here comes the big one . . .
cap deprec:rails:install_rails_stack

ok, it almost made it through ... ran for a few minutes and failed on sqlite3. Specifically, it failed here:

executing `deprec:rails:install'
executing `deprec:rails:install_deps'
executing "sudo -p 'sudo password: ' \n      
sh -c \"DEBCONF_TERSE='yes' DEBIAN_PRIORITY='critical' 
DEBIAN_FRONTEND=noninteractive apt-get -qyu --force-yes  
install libmysqlclient15-dev sqlite3 libsqlite3-ruby libsqlite3-dev \""

.. with the error:

Package sqlite3 is not available, but is referred to by another package. This may mean that the package is missing, has been obsoleted, or is only available from another source. E: Package sqlite3 has no installation candidate

After ssh'ing on the server, fooling around with apt-get myself, googling sqlite3/ubuntu, etc, still no love. So I went ghetto on this one:

sudo vi /opt/local/lib/ruby/gems/1.8/gems/deprec-1.99.13/lib/deprec/recipes/rails.rb

.. and removed the two sqlite related libs from the recipe (sqlite3 libsqlite3-ruby), at around line 77. Bottom line is that all my apps use mysql, so I knew I wouldn't miss sqlite

6) NOW let's setup a rails stack!

Since deprec's installrailsstack had made it almost all the way though, I checked out the recipe to see what's left. Turned out it's just one task:

cap deprec:rails:install

That's it. At this point my server has Rails2, a bunch of gems including mongrel, nginx, mysql, and probably a whole bunch of other stuff I don't know about yet.

7) so . . . how do you deploy to staging?

I didn't want to figure out the "right" way to configure Capistano for a staging environment right now. Plus, my project already has a (non-depified) deploy.rb, which I don't want to mess with right now.

In the interest of expediency, I just checked out a separate copy of my app and:

rm config/deploy.rb
depify .
vi config/deploy.rb

... add set :user, 'root', updated :application, :repository, :domain, and the three roles (:app, :web, :db)

cap setup 

cap deprec:deploy

... and had to work through some problems with access to my SVN repo, which is probably reflective of the sorry state of said repository. As a takeaway, however, note that capistrano2 uses scmusername and scmpassword instead of svnusername/svnpassword.

8) create the database

First you have to create your database user. Again, I know deprec helps with this, but it wasn't immediately obvious to me how to do it. SSHing onto the server and issuing a few commands inside mysql was easy enough though:

mysql> create user general@localhost identified by 'yourpassword';
mysql> GRANT ALL ON *.* TO 'general'@'localhost';

And back on my local machine:

cap deprec:db:create

from here you could do cap deprec:db:migrate, but I wanted a fresh snapshot from production via mysqldump.

9) fire it up

deprec:nginx:restart
deprec:mongrel:restart

It works! Total time elapsed: about three hrs.

This is a good stopping point, since my staging environment is up and running. The next step is to replace Mongrel with Thin -- but that will have to wait for the next post.

Notes on what's where

  • Mongrel Cluster config is in `/etc/mongrelcluster/[appname].yml
  • ninx config is in /usr/local/nginx/vhosts/[app_name].conf

Cheap Rails VPS options

Feb 24 by Andre in Ruby on Rails »

I did some research today on low-cost VPS setups for Rails deployments. My immediate need is to set up some staging environments, but I'm also interested in being able to quickly spawn new production-grade Rails environments as easily (and cheaply) as possible. Note: there's a good discussion on VPS's here in the Rails Business group.

Here are my findings so far:

Who 256mb 512mb 1GB setup fee Rails Stack? Backups Notes
RimuHosting $30 $40 $85 $10-$20 Just ask for it -- Ruby1.8.6 Rails2 Apache2.2 mongrel mysql rmagick "RimuHosting run backups of each VPS once a week. We try to keep 2 copies of the backup" Rimu also gives you 300MB of space on an ftp server -- I use this for rotating mysqldump backups Rimu is the only one of these I've personally used. I have a dedicated box there and VPS's for clients
Linode $19* $29* $60 none None "Backups are your responsibility. You are protected against a hard drive failure on the host, as we utilize hardware RAID 1 mirroring across two drives. However, this is not a substitute for proper backups" *Memory is in odd sizes -- $19 is for 360MB, $29 is for 540MB
SliceHost $20 $38 $70 none They have good instructions for using deprec Cost extra. "At any given time, you have access to 3 images of your system: a daily (less than 24 hours), a weekly (less than 7 days) and a snapshot (variable). Monthly pricing is $5/$10/$15/$30 for 256/512/1024/2048 slices. You can also create a new slice from the backup of another slice (cloning)" *actually have availability right now (2/23/08) on all their slices.
SilverRack $20 $40 $70 none "We have Centos and Debian VPS templates that come with Ruby, Ruby on Rails, Apache 2.2, MySql 5, and ImageMagick installed and ready to go." "We perform nightly backups of all of our customer's VPSs. We keep these backups for 2 days" will give you $10/mo off if you're a member of a Ruby users group
VPSLink $25 $40 $75 none "All of VPSLink's Ruby on Rails templates come with Ruby 1.8.6, Lighttpd, FastCGI, mySQL, and RubyGems 0.9.5 pre-installed"   FastCGI? WTF

Rails stack setup / Application management

For the providers that don't have a Rails stack, there are some good options for setting up your own stack and/or deploying/managing your apps after you get your server running:

  • RailsMachine gem -- Stack setup + App management
  • RubyWorks -- Stack setup -- "RubyWorks implements a load-balanced cluster of Mongrel servers, which in most situations is the best way to deploy a Rails application today. It is packaged as a Yum repository (for RedHat/CentOS) or APT repository (for Debian/Ubuntu)" Works on a range of distros, including Centos 4,5. Uses HAProxy for balancing, doesn't include a web server.
  • Deprec -- Stack setup + App management -- "Deprec is a collection of automated recipes, written in Ruby, for setting up production ready Ruby on Rails servers. This includes everything from creating admin accounts and setting up your ssh keys to compiling and installing the packages required to get a Rails application running on a freshly installed Ubuntu server." Works on Ubuntu 7.10
  • Slingshot gem -- Stack setup + App management -- "a set of recipes, tasks, extensions and plugins that work with Capistrano to setup and configure a server for a Rails Application, quickly, and easily."
  • FiveRun's production stack -- Stack setup -- "provides a fast, easy way to get everything you need to develop and deploy Ruby on Rails applications. RubyStack includes Ruby, Subversion, MySQL, SQLite, ImageMagick and several Ruby Gems, and will optionally install Apache 2.2 with rewrite and proxy support"

Additions / recommendations / corrections? Leave a comment.

PostgreSQL on Leopard gotchas

Jan 16 by Andre in How-to »

For a recent Rails project, I had to use PostgreSQL instead of the standard MySQL for the database. Setting up Postgres on Mac OS 10.5 has some quirks, which I will share with you here.

  • There are three primary ways to get PostGRES onto Leopard: a pre-built binary, MacPorts, and source. My choice was to build with source. There are several good posts on building from source:
  • I do not recommend creating a separate user to run postgres. Doing so clutters your startup screen with another user, and requires you to su to that user to start the database. Instead:

    1) install Postgres as root

    2) after install, from the command line: chown -R andre /usr/local/pgsql/data. The -r flag changes the ownership recursively. Obviously, substitute your own username for "andre" in the example.

  • Since I don't use PostGres all the time, I don't want it to be started up automatically. Instead, I set up two aliases in by .bashrc:

    alias startpostgres='/usr/local/pgsql/bin/pgctl -D /usr/local/pgsql/data -l /usr/local/pgsql/data/logfile start' alias stoppostgres='/usr/local/pgsql/bin/pgctl -D /usr/local/pgsql/data -l /usr/local/pgsql/data/logfile stop'

  • when you start postgres, you'll probably get the dreaded "shared memory error," which looks like this:

    FATAL: could not create shared memory segment: Cannot allocate memory DETAIL: Failed system call was shmget(key=1, size=1081344, 03600). HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory or swap space. To reduce the request size (currently 1081344 bytes), reduce PostgreSQL's sharedbuffers parameter (currently 50) and/or its maxconnections parameter (currently 10).

  • some resources will tell you to edit the /etc/rc file, which is incorrect for Leopard. Instead, create /etc/sysctl.conf (if it does not already exist -- mine didn't), and add the following lines:

    kern.sysv.shmmax=167772160 kern.sysv.shmmin=1 kern.sysv.shmmni=32 kern.sysv.shmseg=8 kern.sysv.shmall=65536

You'll need to su to root to create /etc/rc

Have fun with Postgres!

Geocoding Advanced Rails Recipes

Jan 13 by Andre in How-to » , Speaking / writing »

I have a geocoding recipe coming out in Pragmatic's Advanced Rails Recipes. The recipe is titled "Finding Things by Location," and it offers how-tos and best practices on using my GeoKit plugin to, well, Find Things by Location. The most recent PDF of the beta book includes my recipe along with over 30 other recipes by community leaders like Chris Wanstrath, Dan Benjamin, and Geoffrey Grosenbach, to name just a few.

Be smart about your technical debt

Dec 20 by Andre in Entrepreneurial »

Much of what Rails provides to get your apps up and running isn't optimized for performance. It's crafted to be more efficient for developers, not more efficent at runtime. before_filter callbacks on your RESTful controllers to get the current object? That's an extra database call. All those nifty plugins you are using to kickstart your app? They probably generate far more SQL (and slower SQL) than if you coded the same functionality ad-hoc. ActiveRecord itself is slow compared to raw SQL and object instantiation.

If your project grows huge -- 10's of millions of PV/day huge -- you're gonna have to revisit some of that stuff. Some of it you can compensate for with smart caching techniques and more hardware. And some of it you will have to throw away and rewrite. If you get really huge, you're going to have pay back some of the technical debt you incurred by choosing a tool like Rails.

Yes, using a tool like Rails incurs some debts. But just like the rest of the world, there are good debts and bad debts. If you're smart about the kind of debt you take on, you can build far more, and build it faster.

Many of your projects will never reach the level where you need to "pay back" for all that developer productivity you enjoyed on the front end. That means you can try more ideas, and (hopefully) fail fast at the more speculative ones. If some of your projects do need to scale radically (beyond the basics of better caching, more hardware, etc), you have an incredible amount of upfront productivity you can leverage against that work of -- say -- optimizing some key queries by hand. As long as you go in with eyes wide open and realistic expectations, then I say that's a smart kind of technical debt.

Trying Netbeans was worth it

Dec 02 by Andre in Ruby on Rails »

I just did the last round of updates on PlaceShout using Netbeans 6RC2's Ruby support. Based on my brief exposure, here are some things it offers which made it worth by time in a concrete way.

  1. really excellent svn integration
    • it shows you lines you've added/deleted/changed in your regular editing view, as you work -- it's a great visual cue on the extent of your changes without leaving your normal coding flow.
    • the source compare is outstanding, it highlights not just changed lines but parts of lines. Very smart and intuitive, and better than anything I've used before.
  2. control-click on any method to go to its definition. This is especially useful in .erb templates to go to a helper definition. If there are multiple definitions, Netbeans gives you a list.
  3. as-you-type "jump to class" in addition to "jump to file". Command-o brings it up, and it works on project classes, native ruby, and gem and plugin code. It's snappy enough to be useful, but could get a little faster.
  4. method completion on AR attributes/finders: netbeans gives you a nice as-you-type completion list on the dynamic, data-driven getters/setters Rails infers from the database columns. Nice! There's a lot of other method completion it tries to do, but this is the one that stood out to me.

Netbeans has got a ton of functionality and a rich plugin ecosystems, and I'm sure there are more gems in there. The points I've indicated here are just the ones that were useful, accessible, and intuitive enough to engage me right away.

Tor Norbye is publishing a regular "Ruby Screenshot of the Week", give it a read to see what else is possible.

My take is that if 1) method/paramater completion is refined a bit, 2) debug mode works seamlessly and effortlessly (couldn't get it to work on Leopard), and 3) performance improves a bit -- Netbeans will be a home run for Rails development.

Huge bonus points if the collaboration plugin delivers on its promises (and supports Ruby!)

Introducing PlaceShout

Nov 28 by Andre in PlaceShout »

PlaceShout has hit the streets! What is it? It's a “cheatsheet”-style summary of places around town, created by you and arbitrated by the community. See my full announcement on The Napkin for more details.

PlaceShout

In Your Brain, Everything is a Relative Reference

Nov 25 by Andre in Misc »

Have you noticed how much easier it is to remember directions in your own city? Think about the last time your printer ran out of ink and you had to jot directions to a restaurant on a post-it. Compare that to writing out directions from a hotel to a restaurant in an unfamiliar city.

It's a lot easier on familiar turf. Why? Near home, the directions are anchored by points of familiarity in your mind. You already know how to get to someplace nearby, so you can use that as a ready point of reference. Closer to home, you get to use all kinds of reference points: your work, familiar street names, the park you go to, etc. Because that's the way your brain works. In your brain, everything is a relative reference.

This is equally true if you are communicating directions to someone, rather than just writing them down for yourself. The better you know the person, the easier it is: "go like you're headed to work, but turn left just before that Thai restaurant you like." Not only are the directions concise, they are simple enough that you probably don't need to write them down. Communicating is a lot easier when there are shared experiences, reference points, and a sense of "knowing what the other person knows."

There are lessons in here somewhere for those of us who create software. After all, we spend a lot of time with our computer trying to find things, either on the computer (photos, spreadsheets) or with the computer (a book on Amazon, that page you Delicious'd -- or did you mark it in Google Reader?). I often think of this when I'm using Delicious. I know I bookmarked something, but wading through the tag cloud to find it again takes too long. I usually end up finding it with a few Google searches. When the first search fails, there's usually something in those first results which triggers my memory on the keywords that will retrieve it.

Can software infer what is familiar terrain for us, and provide navigation relative to that? Can Google or Delicious know what my mental "anchors" are, and help me find stuff from there?

An OS-level example: I have a dozen or so Ruby on Rails projects in /Users/andre/projects/rails/, and I spend a lot of time in the immediate subdirectories. If there were a heat map of the places I spend time in, this directory would be hot. Would that be useful as a navigational device? Possibly. If a place got hot enough, the OS could ask me to label it in a way that's meaningful to me. I might use that as a jumping-off point as long as spend a lot of time on Rails projects.

Obviously there are pitfalls when trying to get a computer to guess what you're trying to do, or what's important to you (R.I.P Clippy). Still, there are bound to be payoffs for trying to get the computer to present navigation the way you think, rather than how it computes. A good start is to think about how our brains tend to remember things clustered relative to familiar points of reference.

Tumblin'

Nov 12 by Andre in Misc »

So I set up a tumblelog over at Andre Lewis' tumblelog. Original name huh?

I like tumblr because it is very convenient to post to. Adding the tumblelog may be too many publishing venues for me though. Here's the breakdown:

  • blogging: longer, more analytical or technical posts
  • tumblelog: short posts, bookmarks, pictures from my phone
  • facebook status updates: things that are short and/or ephemeral and/or only of interest to my friends
  • delicious: bookmarks . . . despite the fact that I never look back at them, because Google always leads me to it quicker (this is another post however)

I don't use twitter, except to pipe my Facebook status updates. If I did, it would be for things even more ephemeral than Facebook status updates.

At some point, all this is going to have to come together and be much easier than it is today.