Termistat : a status bar for your terminal
When running background processes that produce detail logging, it’s often difficult to strike the right balance between providing overall status information and details about the current step in the process. It’s helpful to be able to see “tail-like” information at the detail level to monitor and debug your processes; however, it’s also helpful to be able to know summary information, such as the overall progress through the entire task. You can intersperse “record 1 of n” lines in your output, but they are easy to miss in all the noise.
In order to be able to display both types of information concurrently, I built a simple gem called termistat, which allows you to display a status bar for summary information at the top of your terminal in addition to the original detailed output. It was meant to be a whyday contribution, but I didn’t quite finish it in time to be released on whyday…oh well.
Here’s a screenshot of termistat in action:

Termistat requires the ffi-ncurses gem (which requires the ncurses library to be on your system), and has a configuration DSL to customize the appearance somewhat. Check it out and let me know if you have any ideas for improvement!
RailsConf 2010 - Baltimore

Here we go again RailsConf 2010 has started. The keynotes will be streamed online at http://railsconf.com and the slides of the presentation will also be posted there. I’ll provide more links once they become available.
This is the view from my hotel which is 5 minutes from the convention center where RailsConf is going on.


Acceptance Testing with Cucumber
I’m now following the Acceptance Testing with Cucumber tutorial. You can find the app we built, a kanban manager, on github.
Cucumber is executable documentation. Gurken is the DSL used to write your documentation in the form of
Scenario: Given When Then
The app has different git branches for each stage of the application. Checkout the move-card-passing branch for the most complete functionality. It contains great examples of feature test.
master f294f72 patch number
remotes/origin/HEAD → origin/master
remotes/origin/first-feature-failing 475eb7e words
remotes/origin/first-feature-passing e4ea67a gemfile
remotes/origin/latest eacd855 Merge
remotes/origin/master f294f72 patch number
remotes/origin/more-features-failing aa2d97b new failing features
remotes/origin/more-features-passing 03b6b44 added lane ordering
remotes/origin/move-card-failing 02fa766 add move_card feature
- remotes/origin/move-card-passing 8c1d751 move cards from one lane to another
BUILDING AN API WITH RAILS
A great discussion on building APIs using Ruby and Rails:
Sneak peek of Usage Report for Amazon Web Services™
Sneak peek of Usage Report for Amazon Web Services™ from daniel wanja.
MWRC 2010 - Notes from Day 1.
MWRC
Giles Bowkett - making some music with ruby Archaeopteryx
- Giles Bowkett: Archaeopteryx: A Ruby MIDI Generator
- learn probability matrix
- google is easy if you understand prob matrix
- google spell check in 21 lines of python
- wonder how easy OCR would seem in this context?
- don't understand python community.... why are there not more dick jokes about pythons?
- how is there not a web framework called trouser snake?
- oh yeah... better talk about lambdas
James Golick - Cooking with Chef - @jamesgolick github.com/jamesgolick
- Chef: Quick and Tasty Ruby Powered Server Configuration
- sysadmin work is boring
- too many config languages
- amazed if anyone can get nagios working on a consistent basis
- ues recipes to install packages
- recipes written in ruby
- create services -> status, restart, reload, etc.
- templates to create config files
- erb
- notifies restart if config changes
- autoreload on save very handy for things like dynamic lists of ips that change when you start a new EC2 instance
- makes setting up stuff like haproxy and heartbeat easier
- security
- easy to include iptables
- always turn off password ssh logins - easier to remember when part of your cookbook
- look into chef server and chef client
Joe Damato - RVM
- RVM: Ruby Version Manager - RVM Ruby Version Manager - Documentation
- RVM gemset - different gemsets for the same ruby version per project
- create rvmrc to switch env automatically when you cd into a project directory
- export gemsets?
- should you use gemsets or just bundler
Loren Segal - Documentation with YARD
- Yet Another Ruby Documentor
- Talk about documentation in general
- Documentation to help you think about your API
- What makes documentation good?
- consistency -> pick a style and stick with it
- correct -> it can be wrong and should be audited
- coherent
- YARD
- meta-data
- @param [Symbol] req_type :get or :post
- ....
- yard-respec
- shows rspec specs alongside method docs
- yard-sinatra
- shows your routes for api
Michael Jackson - Rack for web developers
- Rack: a Ruby Webserver Interface
- Read the Spec
- blah, blah, blah
- rack is cool in that it allows web frameworks to communicate with web servers, but not sure you care that much unless making a web framework
Yehuda Katz - Modularity - Lessons learned from Rails 3
- Try to become modular too soon and you will be wrong
- Become modular once lack of modularity is hurting you, then decouple
- Constants -> Globals
- router.url_for in rails 3
- easier to track down where instance variables came from than Globals
- eliminate things that are global
- tests are the canary in the coal mine
- instead of hard coding contants, pass things around
- be subspicious of Contant.foo
- stop caring about object allocations
- object allocations are essentially free
- Render
- Controller -> ViewPathSet -> ViewPath -> Template (on file system)
- Used to assume actual file path
- hard to cache
- Template.new takes a path
- Now
- Caller -> LookupContext -> ViewPaths -> PathResolver-> Resolver -> Template
- Template.new takes a source
- Could overide PathResolver to pull from database or S3 or something
- could be useful in making a CMS system with Rails
- Use Modules
- don't put methods you want people to be able to override in a class, make a module
- then you cna call super
- Use ActiveSupport::Concern
Paul Sadauskas - HTTP
- read the spec :-)
- prevent the requests that you don't have to answer
- Persistent Connections - so you don't have to create a new TCP connection for every request --- keepalive=onC
- Caching
- how do you decide when something is stale?
Jeff Casimir - Ruby Processing
- dynamically generate images in ruby app
- uses jruby
- first built to create verticle column headers
- Distributed Programming with Ruby -> to learn how to send jobs to ruby processing from rails
- Beanstalkd -> simple fast background processing -> brew install beanstalkd
MWRC 2010 - Day 1 Live Video
The conference is about to start in 30 minutes, the room starts to buzz. The confreaks guys have their camera and video recording equipment all setup. So you will be able to catch up the conference online soon. Somehow I really like single track conferences and the sessions seem really great and will be fast passed, 30 to 45 minutes. Check out the schedule. So I will sit back and enjoy the show.
Follow it live on Justin TV!!
Watch live video from Mountain West Ruby Conference on Justin.tv
Salt Lake City is definitively a beautiful city, surrounded by it’s mountains…
RMagick (from source) on Snow Leopard
After the release of 10.5, I published an article about building RMagick from source on Leopard. I won’t rehash the why, you can read the original article for that. My clean install necessitated updating the RMagick script, so here’s what worked for me to install from source on Snow Leopard! For the impatient, here’s the download link: rmagick-build.sh
First, we start with installing wget, as it seems to be a bit more clever than curl about dealing with mirrors, etc. Then, we compile and install each prerequisite package. Finally, we install the gem.
All the links in the script worked for me, but, depending on your location, network, conditions, etc, your mileage may vary. Enjoy!
#!/bin/sh # install wget, which is cleverer than curl curl -O http://ftp.gnu.org/gnu/wget/wget-1.11.tar.gz tar zxvf wget-1.11.tar.gz cd wget-1.11 ./configure --prefix=/usr/local make sudo make install cd /usr/local/src # prerequisite packages wget http://nongnu.askapache.com/freetype/freetype-2.3.9.tar.gz tar zxvf freetype-2.3.9.tar.gz cd freetype-2.3.9 ./configure --prefix=/usr/local make sudo make install cd /usr/local/src wget http://superb-west.dl.sourceforge.net/sourceforge/libpng/libpng-1.2.39.tar.gz tar zxvf libpng-1.2.39.tar.gz cd libpng-1.2.39 ./configure --prefix=/usr/local make sudo make install cd /usr/local/src wget ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz tar xzvf jpegsrc.v6b.tar.gz cd jpeg-6b ln -s `which glibtool` ./libtool export MACOSX_DEPLOYMENT_TARGET=10.6 ./configure --enable-shared --prefix=/usr/local make sudo make install cd /usr/local/src wget ftp://ftp.remotesensing.org/libtiff/tiff-3.9.1.tar.gz tar xzvf tiff-3.9.1.tar.gz cd tiff-3.9.1 ./configure --prefix=/usr/local make sudo make install cd /usr/local/src wget http://superb-west.dl.sourceforge.net/sourceforge/wvware/libwmf-0.2.8.4.tar.gz tar xzvf libwmf-0.2.8.4.tar.gz cd libwmf-0.2.8.4 make clean ./configure make sudo make install cd /usr/local/src wget http://www.littlecms.com/lcms-1.17.tar.gz tar xzvf lcms-1.17.tar.gz cd lcms-1.17 make clean ./configure make sudo make install cd /usr/local/src wget ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/GPL/gs870/ghostscript-8.70.tar.gz tar zxvf ghostscript-8.70.tar.gz cd ghostscript-8.70 ./configure --prefix=/usr/local make sudo make install cd /usr/local/src wget ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/GPL/gs860/ghostscript-fonts-std-8.11.tar.gz tar zxvf ghostscript-fonts-std-8.11.tar.gz sudo mv fonts /usr/local/share/ghostscript # Image Magick wget ftp://ftp.fifi.org/pub/ImageMagick/ImageMagick.tar.gz tar xzvf ImageMagick.tar.gz cd `ls | grep ImageMagick-` export CPPFLAGS=-I/usr/local/include export LDFLAGS=-L/usr/local/lib ./configure --prefix=/usr/local --disable-static --with-modules --without-perl --without-magick-plus-plus --with-quantum-depth=8 --with-gs-font-dir=/usr/local/share/ghostscript/fonts --disable-openmp make sudo make install cd /usr/local/src # RMagick sudo gem install rmagick
UPDATE There is a bug with libgomp that breaks the convert utility (See comments below). the --disable-openmp configure option has been added to the script to fix this.
UPDATE 2 A new patchlevel of ImageMagick has been released that supersedes the original one referenced in this script, and the original has been removed from the server. Thanks to Sebastian for this update that will grab the latest release.
MWRC - Thanks you, that what awesome!
Check out some of the comments from the last few hours or check all tweets regarding #mwrc.
MWRC - Moutain West Ruby Conference is about to start.

The Confreaks guys did setup their cameras, sound and lights, so you will certainly be able to see all the talks in a few weeks.
The conference takes place in Salt Lake City, the scenery is impressive as the city is surrounded by high mountains…even for someone living in Denver. The picture above was taken just before the conference starts and shows the atrium we gonna spend the next two days in. The talks looks really cool and tonight the Engine Yard’s Hackfest 2.0 in suite next to mine at the Hilton Salt Lake City Center.
Advanced Ruby - Day 3

The first two days of the training were really excellent. Great pace, clear explanations and samples, very technical, Chad and Dave really rock at Ruby.
Making Domain-Specific Languages
We start with a discussion on DSL versus an API.
Meat-and-Potato DSLs
- Block based API.
- Directly manipulating domain model classes
- Defining classes and methods
- Manually typing repetitive, low-level code
Example is Rake. Rake is a dependency oriented programming language.
Eexample from Dhaka (a paraser generator)
for_pattern("\n") do
create_token("newline")
endmethod_missing Trick
require 'pp'
class CommandListener
def initialize
@commands = []
end
def method_missing(*args)
@commands << args
self
end
end
listener = CommandListener.new
listener.instance_eval do
this object accepts whatever you type and stores it
end
pp listeneroutputs:
#<CommandListener:0x80264 @commands= [[:you, CommandListener], [:whatever, #<CommandListener:0x80264 ...>], [:accepts, #<CommandListener:0x80264 ...>], [:object, #<CommandListener:0x80264 ...>], [:this, #<CommandListener:0x80264 ...>], [:it], [:stores, #<CommandListener:0x80264 ...>]]>
listener = CommandListener.new
listener.instance_eval do
this.object.accepts.whatever.commands.and.stores.it
end
pp listeneroutputs:
#<CommandListener:0x712b4 @commands= [[:this], [:object], [:accepts], [:whatever], [:commands], [:and], [:stores], [:it]]>
Note any keyword can be used with method_missing…E.g. freeze is not a missing method.
Now by using a BlankSlate object we can avoid this issue:
class BlankSlate
instance_methods.each do |method|
undef_method(method) unless method =~ /^__/ || method == 'instance_eval'
end
endWe can now create a command listener that can use any commands:
require 'pp'
class CommandListener < BlankSlate
def initialize
@commands = []
end
def method_missing(*args)
@commands << args unless [:inspect, :to_s].include? args.first
self
end
def pretty_print(pp)
pp.output.write @commands.inspect
end
end
listener = CommandListener.new
listener.instance_eval do
You can even type freeze!
end
pp listenerAnd we get the following output:
[[:freeze!], [:type, #<CommandListener:0x7ee28>], [:even, #<CommandListener:0x7ee28>], [:can, #<CommandListener:0x7ee28>], [:You, #<CommandListener:0x7ee28>]]
On the same principals we just create a morse encoder, and of course Dave had to show off and interface with the speech function of OSX and another version that interfaces with the MIDI controller.
Exotic Control Flow
Creating a loop with continuations
def start_loop
callcc{|c|c }
end
def end_loop(c)
c.call(c)
end
i = 0
again = start_loop
puts i
i += 1
end_loop(again) unless i > 5Moving on…
We voted on what to cover next as we won’t have time to cover every thing…and the winners are:
* Concurrency .................. * Debugging/Profiling ................ * JRuby ...... * Ruby Extras ........... * Distributed Programming ......................
Distributed Programming
DRb
Marshaling
>> h = {:x => 1}
>> Marshal.dump(h)
=> “\004\b{\006:\006xi\006”
>> Marshal.load(_)
=> {:x=>1}
DRB Server
require 'drb/drb'
require 'ostruct'
DRb.start_service("druby://localhost:4321", OpenStruct.new)
DRb.thread.joinDRb Client
require ‘drb’
DRB.start_service
o = DRbOject.new_with_url("druby:''localhost:4321")
o.last_accessed = Time.now
o.some_other_arbitrary_method = "Set this on the open struct"By default Pass-by-value, but can be Pass-by-reference can be enabled by including DRbUndumped.
- Rinda
- Ring
…
That’s all Folk! …my hands/brain where running tired during the last hour :-)
That was an incredible 3 days thanks to Chad and Dave. So if you want to dive deeper in Ruby, the Advanced Ruby is the best way to get there!
Enjoy!
Daniel


