What?
Why?
Three coffee cups later
Ruby, Javascript & OS X
What?
8
comments
Labels:
blog,
Bye Bye,
narcvs,
why worry?,
Word press
Today the Pollen count hit the ceiling. Every year this happens, and every year I am just as surprised to find myself floored around the time the weather turns warm.
I've often said that there are two weeks of good weather in Chicago every year - one as hot summer turns to cold winter, and another when cold winter turns to hot summer.

1 comments
Labels:
chicago,
Pollen
I just received the following in my mail:
1 comments
Labels:
Globus,
Google,
Google Summer of Code,
Open Source
What?
mash = Mash.new
mash.author!.name = "Michael Bleigh"
mash.author.info!.url = "http://www.mbleigh.com/"
sudo gem install mash
git clone git://github.com/mbleigh/mash.gitWhat?
A way to get your website cross-browser compatible Column layout ready in 30 seconds or less.
Why?
Column layouts is traditionally done with tables. WRONG.
YUI grids css gives you a cross browser compatible column layout, and the YUI builder helps you construct the HTML skeleton in a neat wysiwyg fashion.
How?
Go over to http://developer.yahoo.com/yui/grids/builder and build your layout.
Then just hit the Code button and get the plain text - voila. It also resets your fonts to make for a really nice, discreet default look that you can then modify.


What?
OpenID is a way to sign in once, and only once, for all your web services. Only problem is: you need an OpenID account provider. Not anymore - just use your Google Account (Because we all have those, right?)
How?
Just go to http://openid-provider.appspot.com/. Google takes care of the rest.
What?
Some thoughts on how to organize your javascript file structure and encode your database models to json or HTML for the wire. They were inspired by an email from a guy in Germany in response to my Online Desktop demo presentation on YouTube.
Why?
MVC is a great way to organize your web apps - it makes you write good code! However, fitting snippets of html and javascript code for ajax type pulling into the picture is not necessarily obvious.
How?
I think there are a few good ways to do this, and a mix of them all is probably the right way to go. As I see it, there are three ways to deliver your js code to the client, and two ways to dynamically process and display database objects from the server on the client side:
Deliver JS
static js file inclusion (<script src=""> tag)
dynamic js file inclusion (a la dojo.require('...')
ajax request + eval on content (harder to debug and potentially unsafe)
Deliver objects and visualize them
Send json down the wire, sanitize (still a risky business), and eval (if you're using EXTjs, use it's util parseJSON method)
Send html down the wire, and use jquery's $('div').html(htmlVar) or Ext's equivelant
In Ruby on Rails, I do the first two by just including files in my /javascript/file.js directory. That's where I keep all my application code, like layout, event hooks, utility functions etc. Neatly organized into separate files, I can then easily mash them all into a single file at production time to save connections/bandwidth.
I rarely use the third option of sending javascript down the wire and running it. If you have something like GWT producing the code for you, that's fine, but otherwise I feel like it just breaks the MVC structure.
To maintain a continuous and manageble way to send my objects down the wire I tend to have two methods for each object I'm dealing with: to_html and to_json. The client then uses a query parameter to specify which format I wants the response in, and then uses setHtml(response.responseText) or eval('var obj = '+response.responseText); (with some sanitization done first).
That way I can implement the methods on the server side to very easily encode the object for display, send it, and display it however I want. A user account for example, could in ruby do:
class User < ActiveRecord::Base
def to_html
['name','email','phone'].collect do |attribute|
"#{self.send(attribute)}"
end
end
def to_json
{:name => name, :email => email, :phone => phone}.to_json
end
end
$('#button').click(function(user){
$.ajax('/users/view'+user.id,{
data : {
id : user.id,
format : 'html'
},
complete : function(response) {
$('#output').html(response.responseText);
}
});
});
# Users controller
def view params
render :text => User.find(params[:id]).send("to_#{params[:format]}".to_sym)
end

Introduction - The Grid.
Grid computing promises the potential to coordinate vastly distributed computational resources into a coherent whole. In doing so it poses qualitatively novel challenges to the field of technology. The socio-political structure among Grid participants is far from obvious; the software communication protocols are complex; and the actual deployment of a ready service onto a grid is exceptionally non-trivial.
Assuming that we have a working grid at our hands, the development, deployment and maintenance of a service is still difficult. At the moment, the participation threshold for anyone but the technology wiz is simply too high. Thus we aim to create a browser-based user interface with the goal to bridge the gap between the highly domain specific complexities of WSDL/WSRF/etc and a seamless user experience. Imagine a South American student on an XO laptop successfully deploying a Grid service - that's our dream.
Conceptual design: After discovering services by search
and by browsing the service archives, a service flow is
easily created by connecting services to each other.
In short: Grid computing has huge potentials but is still a young technology and extremely difficult to use. In order to leverage its fullest potential the participation threshold has to be lowered, and the user experience made more pleasant.
Our particular choice of a browser-based GUI has the obvious benefit of easy distribution and minimal client requirements.
What?
Signal trapping and processing in Ruby - it's way easy.
Why?
Signals are very useful, e.g. to detect shutdown and let your program clean up after itself.
How?
Here's a quickie that'll get you started playing.
# Let's see which signals we can trap
{
"ABRT"=>6, "ALRM"=>14, "BUS"=>7,
"CHLD"=>17, "CLD"=>17, "CONT"=>18,
"FPE"=>8, "HUP"=>1, "ILL"=>4,
"INT"=>2, "IO"=>29, "IOT"=>6,
"KILL"=>9, "PIPE"=>13, "PROF"=>27,
"QUIT"=>3, "SEGV"=>11, "STOP"=>19,
"SYS"=>31, "TERM"=>15, "TRAP"=>5,
"TSTP"=>20, "TTIN"=>21, "TTOU"=>22,
"URG"=>23, "USR1"=>10, "USR2"=>12,
"WINCH"=>28, "XCPU"=>24, "XFSZ"=>25
}.each do |signal,num|
puts "Set up trap for #{signal} #{num}"
trap signal do
puts "#{signal} #{num} was trapped"
end
end
# Sleep away and lets press some buttons. Try for example ctr-c
sleep 100
at_exit do
puts "I'm quitting now!"
end
4
comments
Labels:
at_exist,
destroy,
initialize,
INT,
interrup,
process,
Ruby,
SIGINT,
signal processing,
Signals
What?
Behavior driven coding for Ruby, and especially, Ruby on Rails.
This is a summary and run-through of the excellent RailsEnvy Love Tests presentation.
Why?
gem install rspec
ruby script/plugin install svn://rubyforge.org/var/svn/rspec/tags/CURRENT/rspec
ruby script/plugin install svn://rubyforge.org/var/svn/rspec/tags/CURRENT/rspec_on_rails
./script/generate rspec
rake rspec
gem install ZenTest redgreen
autotest
@user = mock_model(User).stub!(:first_name).returns("Greg") # Let there be a Greg
@user = mock_model(User, :first_name => "Greg") # Briefer syntax
User.stub!(:find_by_email).returns(@user) # Always find Greg
validates_presence_of :first_name
# To test it =>
@user.should_have_at_least(1).errors_on(:first_name)
has_many :user_roles
# Test
@user.user_roles.create(:role => "Admin")
@user.user_roles.count.should == 1
redirect_to :action => 'index'
# Test
response.should redirect_to(:action => "index")
What?
A quick tutorial to how to publish your ruby gems to the rubyforge gem listing in just under 10 minutes.
This is a fat-reduced version of nuby on rails' tutorial. Thanks for the great info!
Why?
You want to share your code, right? Sharing your ruby code is *really easy*!
How?
Using hoe. This assumes you already have a rubyforge account and a project approved. See https://rubyforge.org/account/register.php to set up an account and http://rubyforge.org/register/projectinfo.php to register a project.
Setup
sudo gem install hoe --include-dependencies
# ~/.bash_login
export EDITOR=/usr/bin/mate -w
Log in to rubyforge
rubyforge setup
Sow your project
rubyforge login
sow object-stash
History.txt
Manifest.txt
Rakefile
README.txt
bin
sparklines
lib
sparklines.rb
test
test_sparklines.rb
p.remote_rdoc_dir = '' # Release to root
rake check_manifest
== 1.0.1
* New version
* Features
# lib/object-stash.rb
class ObjectStash
VERSION = '1.0.1'
end
rake release VERSION=1.0.1
rake publish_docs
sudo gem install object-stash
0
comments
Labels:
Distribution,
Gem,
Open Source,
Ruby,
Rubyforge,
Software
What?
A way to store entire Ruby objects to disk.
Why?
Let's say you have a data structure that takes a long time to build, e.g. dictionary trie for the English language.
It wold be nice to be able to compute this data structure only once, then store it in some way for later retrieval.
How?
Using Ruby's standard library Marshal class, we can easily serialize an object and write it to disk. Combined with the gzip library we even have efficient storage.
Here's the result:
require 'zlib'
# Save any ruby object to disk!
# Objects are stored as gzipped marshal dumps.
#
# Example
#
# # First ruby process
# hash = {1 => "Entry1", 2 => "Entry2"}
# ObjectStash.sotre hash, 'hash.stash'
#
# ...
#
# # Another ruby process - same_hash will be identical to the original hash
# same_hash = ObjectStash.load 'hash.stash'
class ObjectStash
# Store an object as a gzipped file to disk
#
# Example
#
# hash = {1 => "Entry1", 2 => "Entry2"}
# ObjectStore.store hash, 'hash.stash.gz'
# ObjectStore.store hash, 'hash.stash', :gzip => false
def self.store obj, file_name, options={}
marshal_dump = Marshal.dump(obj)
file = File.new(file_name,'w')
file = Zlib::GzipWriter.new(file) unless options[:gzip] == false
file.write marshal_dump
file.close
return obj
end
# Read a marshal dump from file and load it as an object
#
# Example
#
# hash = ObjectStore.get 'hash.dump.gz'
# hash_no_gzip = ObjectStore.get 'hash.dump.gz'
def self.load file_name
begin
file = Zlib::GzipReader.open(file_name)
rescue Zlib::GzipFile::Error
file = File.open(file_name, 'r')
ensure
obj = Marshal.load file.read
file.close
return obj
end
end
end
if $0 == __FILE__
require 'test/unit'
class TestObjectStash < Test::Unit::TestCase
@@tmp = '/tmp/TestObjectStash.stash'
def test_hash_store_load
hash1 = {:test=>'test'}
ObjectStash.store hash1, @@tmp
hash2 = ObjectStash.load @@tmp
assert hash1 == hash2
end
def test_hash_store_load_no_gzip
hash1 = {:test=>'test'}
ObjectStash.store hash1, @@tmp, :gzip => false
hash2 = ObjectStash.load @@tmp
assert hash1 == hash2
end
def test_self_stash
ObjectStash.store ObjectStash, @@tmp
assert ObjectStash == ObjectStash.load(@@tmp)
end
def test_self_stash_no_gzip
ObjectStash.store ObjectStash, @@tmp, :gzip => false
assert ObjectStash == ObjectStash.load(@@tmp)
end
end
end
# Here's our theory of everything - make it heavy
theory_of_everything = { :question => "Life, Universe & Everything", :answer => 42 }
1000.times {|i| theory_of_everything[i] = "rubbish#{i}" }
# Stash it
ObjectStash.store theory_of_everything, './theory_of_everything.stash'
# Let's see what it did
File.stat('./theory_of_everything.stash').size # => 4206
# Reload it
loaded_theory_of_everything = ObjectStash.load 'theory_of_everything.stash'
question = loaded_theory_of_everything[:question]
answer = loaded_theory_of_everything[:answer]
puts "The answer to #{question} is #{answer}" # => The answer to Life, Universe & Everything is 42
def report msg
puts msg
t=Time.now
yield
puts " -> #{Time.now-t}s"
end
def test_hash_equality hash1, hash2
throw :HashesNotEqual unless hash1 == hash2
throw :HashesNotTreeEqual unless hash1 === hash2
hash1.each do |key,value|
throw :HashCopyDoesNotHaveKey unless hash2.has_key? key
throw :HashCopyDoesNotHaveValue unless hash2.has_value? value
end
end
original_hash = Hash.new
loaded_hash = nil
marshal_dump = nil
report "Build a big hash to be marshalled" do
(0..1000).each do |i|
original_hash[i] = "Entry #{i}"
end
end
report "Store the hash" do
marshal_dump = Marshal.dump(original_hash)
end
report "Load a hash from the dump" do
loaded_hash = Marshal.load(marshal_dump)
end
report "Assert hashes are equal" do
test_hash_equality original_hash, loaded_hash
end
report "Write the marshal dump to file" do
file_out = File.new("marshal_test.tmp",'w')
file_out.write(marshal_dump)
file_out.close
end
report "Construct hash from the marshal file dump" do
file_in = File.new('marshal_test.tmp','r')
loaded_hash = Marshal.load(file_in.read)
file_in.close
end
report "Assert hashes are equal" do
test_hash_equality original_hash, loaded_hash
end
require 'zlib'
report "Gzip the marshaled dump" do
file = File.new('marshal_test.tmp.gz','w')
gz = Zlib::GzipWriter.new(file)
gz.write marshal_dump
gz.close
end
report "Gunzip the marshaled dump and load it" do
gz = Zlib::GzipReader.open('marshal_test.tmp.gz')
loaded_hash = Marshal.load gz.read
gz.close
end
report "Assert hashes are equal" do
test_hash_equality original_hash, loaded_hash
end
puts "Success!"
"Logs you in rapidly (even with your iPhone)"
I've finally gotten the UoC login bookmarklet (post) to work reliably on the iPhone.
Ge it by saving this UoC Quickie3 link as a bookmark, either by dragging it to your toolbar or right-clicking and saving as a bookmark/favorite.
Two notes of caution: If you enter your information incorrectly the first time you will have to delete your cookies manually to get it to work again. The user name and password is saved scrambled, but in decodable plaintext. As always, protect your cookies.
0
comments
Labels:
iPhone,
University of Chicago,
UoC Quickie,
Utility
What?
Html-R, an ajaxified online Ruby2HTML converter.
Why?
When you share your code online, it should look good and be readable, just like in your favorite text editor (emacs, right?).
With TextMate inspired syntax highlighting, Html-R quickly turns this
into that
# Why's (Poignant) Guide to Ruby - The Endertrombe Wishmaker
require 'endertromb'
class WishMaker
def initialize
@energy = rand( 6 )
end
def grant( wish )
if wish.length > 10 or wish.include? ' '
raise ArgumentError, "Bad wish."
end
if @energy.zero?
raise Exception, "No energy left."
end
@energy -= 1
Endertromb::make( wish )
end
end
# Why's (Poignant) Guide to Ruby - The Endertrombe Wishmaker
require 'endertromb'
class WishMaker
def initialize
@energy = rand( 6 )
end
def grant( wish )
if wish.length > 10 or wish.include? ' '
raise ArgumentError, "Bad wish."
end
if @energy.zero?
raise Exception, "No energy left."
end
@energy -= 1
Endertromb::make( wish )
end
end


0
comments
Labels:
ajax,
css,
javascript,
jQuery,
Ruby,
Ruby2Html,
Syntax,
TextMate
What?
How to get many to many relations working quickly with Rails 2.0.2 and sqlite3 3.4.0.
Why?
Many to Many database relations between two models (tables) requires a middle table which records the relation. This can be difficult to get right, but Rails has some awesome helper functions to get you up and running quickly.
... when it works.
When it doesn't, you're likely to see the following:
"SQL logic error or missing database"
Which is about as descriptive as "it's not working." The kink is that Active Record (rails' database interface) will try to set the id field of the relational table, which is reserved by default as the primary key and therefore cannot be set to the same value twice (which rails will do).
How?
First create the models
./script/generate scaffold Actor first_name:string last_name:string
./script/generate scaffold Movie name:string
Then create a migration to set up the relational table:
./script/generate migration AddActorsMoviesRelation
Edit ./db/migration/xyz_AddActorsMoviesRelation.rb:
(Thanks EyeDeal for the :id => false tip!)
class AddActorsMoviesRelation < ActiveRecord::Migration
def self.up
create_table :actors_movies, :id => false do |t|
t.integer :actor_id, :foreign_key => true
t.integer :movie_id, :foreign_key => true
end
end
def self.down
drop_table :actors_movies
end
end
class Actor < ActiveRecord::Base
has_and_belongs_to_many :movies
end
class Movie < ActiveRecord::Base
has_and_belongs_to_many :movies
end
crime_fiction = Movie.create :name => "Crime Fiction"
san_fransisco = Movie.create :name => "The Streets of San Francisco"
jon = Actor.create :first_name => 'Jonathan', :last_name => 'Elliot'
jesse = Actor.create :first_name => 'Jesse', :last_name => 'Friedman'
dan = Actor.create :first_name => 'Dan', :last_name => 'Bakkedahl'
crime_fiction.actors << jon
jesse.movies << crime_fiction
dan.movies << crime_fiction
crime_fiction.actors.each {|actor| puts "#{actor.last_name}, #{actor.first_name}" }
# => Elliot, Jonathan
# => Friedman, Jesse
# => Bakkedahl, Dan
san_fransisco.actors << jesse
jesse.movies.each {|movie| puts movie.name }
# => Crime Fiction
# => The Streets of San Francisco
6
comments
Labels:
Crime Fiction,
Rails 2.0.2,
Ruby on Rails,
sqlite3
What?
A one click solution to log in to the University of Chicago wireless network - the UoC Quickie3. Drag the link to your bookmark toolbar. Next time you want to log in to the UoC wireless, just click the bookmark. It'll take care of the rest.
4
comments
Labels:
Bookmarklet,
University of Chicago,
Utility
What?
An automatic installation script for the ExtJS scaffold generator plugin (demo keynotes)to get you up and running.
Why?
Rails' scaffolding gets you up an running lightning fast. ExtJS is a wonderful javascript desktop library. Let's marry them
How?
Run the following script - it will
# Create the app
rails ext_scaffold_setup
cd ext_scaffold_setup
# Install the plugin and extjs
script/plugin install http://rug-b.rubyforge.org/svn/ext_scaffold
curl -O http://extjs.com/deploy/ext-2.0.2.zip
unzip -q ext-2.0.2.zip
rm ./ext-2.0.2.zip
mv ./ext-2.0.2 ./public/ext
# Generate some scaffolds - posts and purchases
./script/generate ext_scaffold post title:string body:text
./script/generate ext_scaffold purchase order_id:integer amount:decimal description:text
# Create the database for the models
rake db:migrate
# Create links to the models on the landing page
echo '<title>ExtJS Scaffold generator sample</title>echo '<style type="text/css" media="screen">a {text-decoration:none; color:#abc}</style><a href="http://www.blogger.com/posts">Posts</a> <a href="http://www.blogger.com/purchases">Purchases</a>' > ./public/index.html
# All set, run the server!
./script/server
6
comments
Labels:
ExtJS,
Install,
javascript,
Ruby on Rails,
Utility
Shadows play a tremendous roles in our visual understanding of depth. This can be used to trick the eye:
In the above image, the color of square B is, in fact, the same as that of square A. Don't believe me? These are small crops of the above image:

However, shadows are also very important to aid the eye. Or so we learned in Graphics. So we had to make shadows for a map. Manually.
Here's the map without shadows. Green is lowland, red is highland, black and white even higher.
And, with shadows:
Aiding, huh? Aaaand, just the shadows... Please note that each of these pixels is calculated based on two values - an evelation coordinate (z) of the map at any given point (x,y), and a static directional (x,y,z) vector of sun light.

0
comments
Labels:
Graphics,
Open Source,
OpenGL,
Shadows