Time-lapse of the University Tower

Posted by John Wulff Sun, 29 Jun 2008 23:00:17 GMT

My first attempt at a time-lapse. I’ll pick a more interesting subject next time.

This American Life on the Economy

Posted by John Wulff Mon, 12 May 2008 23:13:00 GMT

The most recent episode of This American Life was especially fantastic. They did a great end-to-end explanation of the mortgage mess and the current credit crunch in the fantastic narrative style they’re so good at.

A special program about the housing crisis. We explain it all to you. What does the housing crisis have to do with the collapse of the investment bank Bear Stearns? Why did banks make half-million dollar loans to people without jobs or income? And why is everyone talking so much about the 1930s? It all comes back to the Giant Pool of Money.

Give it a listen and subscribe to the podcast.

How I Deploy Typo Using Capistrano

Posted by John Wulff Wed, 30 Apr 2008 21:03:00 GMT

I’ve been deploying all of my Rails apps with Capistrano to a MySQL, Nginx, Mongrel, God stack for a while.

I hadn’t been keeping my (this) Typo install up to date because it was such a pain to upgrade it compared to my other apps. Not anymore!

Here is my awesome Capistrano deploy task for Typo. (And my database.yml, god.config, and nginx.conf for good measure).

Any way it can be improved?

deploy.rb:
set :application,      'www.johnwulff.com'
set :typo_plugins,     [ 'delicious_sidebar', 'flickr_sidebar' ]
set :user,             'rails_admin'
set :deploy_to,        "/var/www/#{application}"
# If you change the repository be sure to flush the server's cached checkout.
set :repository,       'http://svn.typosphere.org/typo/tags/release_5_0_3'
set :typo_plugins_url, 'http://svn.typosphere.org/typo/plugins/'
# This will substantially speed things up and save typoshphere.or's bandwidth.
set :deploy_via,       :remote_cache

role :app, 'www.johnwulff.com'
role :web, 'www.johnwulff.com'
role :db,  'www.johnwulff.com', :primary => true

namespace :deploy do
  task :default do
    transaction do
      update_code
      typo_plugins.each do |plugin|
        run "cd #{current_release}; script/plugin install #{typo_plugins_url}#{plugin}"
      end
      web.disable
      symlink
      # Copy local database.yml to the new remote release.
      put File.read(File.join(File.dirname(__FILE__), 'database.yml')),
          File.join(current_release, 'config', 'database.yml')
      # Copy local nginx.conf to the new remote release.
      put File.read(File.join(File.dirname(__FILE__), 'nginx.conf')),
          File.join(current_release, 'config', 'nginx.conf')
      # Copy local god.config to the new remote release.
      put File.read(File.join(File.dirname(__FILE__), 'god.config')),
          File.join(current_release, 'config', 'god.config')
      migrate
    end
    # Stop God watches, load the fresh God config that was just uploaded, and
    # then start God watches.
    sudo "god stop #{application}"
    sudo "god load #{File.join deploy_to, 'current', 'config', 'god.config'}"
    sudo "god start #{application}"
    # Reload Nginx configuration without restarting Nginx.
    sudo "/etc/init.d/nginx reload"
    web.enable
    # Don't use sudo for cleanup.  This takes a bit longer than using sudo, but
    # it's not a good idea to give passwordless `sudo rm` permissions to
    # anyone.
    set :use_sudo, false
    cleanup
    set :use_sudo, true
  end
end
database.yml:
production:
  adapter: mysql
  database: johnwulff
  username: johnwulff
  password: *****
  host: localhost
god.config:
#!/usr/bin/env ruby
APPLICATION = 'www.johnwulff.com'
RAILS_ROOT = "/var/www/#{APPLICATION}/current"

%w{9900 9901 9902}.each do |port|
  God.watch do |w|
    pid_file = File.join RAILS_ROOT, 'tmp', 'pids', "mongrel.#{port}.pid"
    log_file = File.join RAILS_ROOT, 'log', "mongrel.#{port}.log"

    w.uid = 'rails_admin'
    w.gid = 'rails_admin'
    w.group = APPLICATION

    w.name = "#{APPLICATION}-mongrel-#{port}"
    w.interval = 30.seconds # default      

    w.start = "mongrel_rails start -d -e production -a 127.0.0.1 -c #{RAILS_ROOT} --user rails_admin --group rails_admin -p #{port} -P #{pid_file} -l #{log_file}"
    w.stop = "mongrel_rails stop -P #{pid_file}"
    w.restart = "mongrel_rails restart -P #{pid_file}"
    w.start_grace = 10.seconds
    w.restart_grace = 10.seconds
    w.pid_file = pid_file

    w.behavior(:clean_pid_file)

    w.start_if do |start|
      start.condition(:process_running) do |c|
        c.notify = 'john'
        c.interval = 5.seconds
        c.running = false
      end
    end

    w.restart_if do |restart|
      restart.condition(:memory_usage) do |c|
        c.notify = 'john'
        c.above = 150.megabytes
        c.times = [3, 5] # 3 out of 5 intervals
      end

      restart.condition(:cpu_usage) do |c|
        c.above = 50.percent
        c.times = 5
      end
    end

    # lifecycle
    w.lifecycle do |on|
      on.condition(:flapping) do |c|
        c.notify = 'john'
        c.to_state = [:start, :restart]
        c.times = 5
        c.within = 5.minute
        c.transition = :unmonitored
        c.retry_in = 10.minutes
        c.retry_times = 5
        c.retry_within = 2.hours
      end
    end
  end
end
nginx.conf:
upstream johnwulff {
  server 127.0.0.1:9900;
  server 127.0.0.1:9901;
  server 127.0.0.1:9902;
}

server {
  server_name johnwulff.com;
  rewrite ^/(.*) http://www.johnwulff.com/$1 permanent;
}

server {  
  listen  80;
  server_name  www.johnwulff.com;
  root /var/www/in_out_open/current/public;
  access_log  /var/www/www.johnwulff.com/shared/log/nginx.access.log  main;
  client_max_body_size  50M;
  # Redirect all traffic to maintenance.html if it exists.
  if (-f $document_root/system/maintenance.html){
    rewrite  ^(.*)$  /system/maintenance.html last;
    break;
  }
  location / {
    # redirect feed requests to feedburner, unless its the feedburner agent
    if ($http_user_agent !~ FeedBurner) {
      rewrite ^/articles.(rss|atom)$ http://feeds.feedburner.com/johnwulff;
      rewrite ^/xml/(atom|rss|rss20)/feed.xml$ http://feeds.feedburner.com/johnwulff;
      rewrite ^/rss$ http://feeds.feedburner.com/johnwulff;
      rewrite ^/feed/(atom|rss|rss20).xml$ http://feeds.feedburner.com/johnwulff;
    }
    # Forward header information so rails can make use of it.
    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect false;
    proxy_max_temp_file_size 0;
    # check for index.html for directory index
    # if its there on the filesystem then rewite 
    # the url to add /index.html to the end of it
    # and then break to send it to the next config rules.
    if (-f $request_filename/index.html) {
      rewrite (.*) $1/index.html break;
    }
    # this is the meat of the rails page caching config
    # it adds .html to the end of the url and then checks
    # the filesystem for that file. If it exists, then we
    # rewite the url to have explicit .html on the end 
    # and then send it on its way to the next config rule.
    # if there is no file on the fs then it sets all the 
    # necessary headers and proxies to our upstream mongrels
    if (-f $request_filename.html) {
      rewrite (.*) $1.html break;
    }
    if (!-f $request_filename) {
      proxy_pass http://johnwulff;
      break;
    }
  }
  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   html;
  }
}

Shultzy's New Website and Twitter

Posted by John Wulff Wed, 16 Apr 2008 21:37:00 GMT

Shultzy’s has a new website, check it out.

Shultzy's New Website

Also, I found their not-yet-publicized Twitter account. One more reason to frequent Shultzy’s! (I really didn’t need any more reasons to frequent Shultzy’s.)

Shultzy's Twitter Feed

Jericho

Posted by John Wulff Sun, 30 Mar 2008 03:08:00 GMT

According to TrekMovie.com Jericho, officially cancelled (again) by CBS, is looking for a new home.

This time, instead of peanuts I’m going to send a nice old-fashioned letter to the SciFi channel.

If you’d like to tell SciFi how happy you’d be if they picked up Jericho you can send a letter to:

SciFi Channel
21st Floor
30 Rockefeller Plaza
New York, NY 10112

I’ll be sending a letter on Monday.

Install id3lib-ruby gem on OS X Leopard 2

Posted by John Wulff Sun, 16 Mar 2008 22:12:00 GMT

After a few hours of struggling to get id3lib-ruby to install on my Leopard machine I came across http://rubyforge.org/forum/forum.php?forum_id=18544:
Posted By: Robin Stocker
Date: 2007-10-28 18:12
Summary: Install on Mac OS X 10.5 (Leopard)
Project: id3lib-ruby

Here’s a quick tip for people having difficulties installing id3lib-ruby on the newest OS X:

http://trac.macosforge.org/projects/ruby/wiki/Troubleshooting#IcannotbuildrubymysqlonLeopardwithmysql.combinaries

In short, here’s how to install id3lib-ruby (after having installed id3lib):

sudo -s
ARCHFLAGS="-arch i386" gem install id3lib-ruby

Thanks a lot Robin, I was starting to go crazy…

Food Fight

Posted by John Wulff Sun, 16 Mar 2008 01:24:00 GMT

I don’t normally post videos but this is amazing.

iTunes Rental Horizontally Squished

Posted by John Wulff Sun, 09 Mar 2008 00:07:00 GMT

Anyone else rent The Edge from iTunes and notice that it is horizontally squished?

Apple, you really should rip these movies with a little more care. Nothing is more annoying than watching a movie with a distorted aspect ratio.

static-gmaps: Google Static Maps API Interface 3

Posted by John Wulff Mon, 25 Feb 2008 21:32:00 GMT

I’ve written my first gem: static-gmaps. It provides a simple interface to the Google Static Maps API.

Usage

map = StaticGmaps::Map.new :center   => [ 40.714728, -73.998672 ],
                           :zoom     => 5,
                           :size     => [ 500, 100 ],
                           :map_type => :roadmap,
                           :key      => 'ABQIAAAA3HdfrnxFAPWyY-aiJUxmqRROGu07ZpoXmWqnENIWDDAF-b-TwhQ4JdQya7b6I5CihUtHtwmmBzWc0Q'
map.markers << StaticGmaps::Marker.new(:latitude => 40,
                                       :longitude => -73,
                                       :color => :blue,
                                       :alpha_character => :b)
map.url => 'http://maps.google.com/staticmap?center=40.714728,-73.998672&key=ABQIAAAA3HdfrnxFAPWyY-aiJUxmqRROGu07ZpoXmWqnENIWDDAF-b-TwhQ4JdQya7b6I5CihUtHtwmmBzWc0Q&map_type=roadmap&markers=40,-73,blueb&size=500x100&zoom=5'

Installation

sudo gem install static-gmaps

Documentation

http://static-gmaps.rubyforge.org

Update February 27, 2007: Added markers.

My Beautiful Controller Spec

Posted by John Wulff Fri, 15 Feb 2008 23:21:00 GMT

Today I spent a few hours refining my controller rspec pattern. I’m really pleased with it.

This controller:
class AssignmentsController < ApplicationController  
  def index
    if params[:person_id]
      @person = Person.find params[:person_id]
      @assignments = @person.assignments
      @title = "Assignments for #{@person}"
    elsif params[:course_id]
      @course = Course.find params[:course_id]
      @assignments = @course.assignments
      @title = "Assignments for #{@course}"
    else
      @assignments = Assignment.find :all
      @title = "All Assignments"
    end

    @ical_url = url_for({ :format => :ics }.merge(params))
    @rss_url = url_for({ :format => :rss }.merge(params))
  end
end
Gets this spec:
require File.dirname(__FILE__) + '/../spec_helper'

describe AssignmentsController do
  describe 'index action GET request with' do
    describe 'no parameters' do
      before(:each)                    do get 'index' end
      it 'should successfully respond' do response.should be_success end
      it 'should assign a title'       do assigns[:title].should == 'All Assignments' end
      it 'should assign assignments'   do assigns[:assignments].should == Assignment.find(:all) end
    end

    describe 'a valid person_id' do
      before(:each)                    do get 'index', :person_id => (@person = test_person) end
      it 'should successfully respond' do response.should be_success end
      it 'should assign a title'       do assigns[:title].should == "Assignments for #{@person}" end
      it 'should assign assignments'   do assigns[:assignments].should == @person.assignments end
    end

    describe 'a valid course_id' do
      before(:each)                    do get 'index', :course_id => (@course = test_course) end
      it 'should successfully respond' do response.should be_success end
      it 'should assign a title'       do assigns[:title].should == "Assignments for #{@course}" end
      it 'should assign assignments'   do assigns[:assignments].should == @course.assignments end
    end

    describe 'any valid parameters' do
      before(:each)                    do get 'index' end
      it 'should assign a rss_url'     do assigns[:rss_url].should == 'http://test.host/assignments.rss' end
      it 'should assign an ical_url'   do assigns[:ical_url].should == 'http://test.host/assignments.ics' end
    end
  end
end

Liberal use of nesting, alignment, and inline assignments, hooray.

Beautiful specs mean I’m that much more likely to actually write them…

Can it get any better?

Older posts: 1 2 3 4


h %s", link_to ('scribbish', 'http://quotedprintable.com/pages/scribbish'))%>