The much awaited BOTS Bootcamp is to happen this weekend.
Date: 4 Dec 2011
What time: 9:30am – 11:30am
Where: BumsOnTheSaddle
The Bootcamp is aimed at getting a biker comfortable owning his/her bike and understand how they can derive the max out of it.
What we intend to cover at the BOTS BootCamp
If you have not yet received an invite and would like to attend this, please do send us an email at admin@bumsonthesaddle.com
The much awaited BOTS Bootcamp is to happen this weekend.
Date: 4 Dec 2011
What time: 9:30am – 11:30am
Where: BumsOnTheSaddle
The Bootcamp is aimed at getting a biker comfortable owning his/her bike and understand how they can derive the max out of it.
What we intend to cover at the BOTS BootCamp
If you have not yet received an invite and would like to attend this, please do send us an email at admin@bumsonthesaddle.com
Prune's butter-crumbed eggs with stewed chickpeas might just be the best breakfast I've had since my birthday migas in Austin. The crunchy coating on the runny egg adds a dash of textural contrast to the largely soft meal, and the preserved lemon on top of the Moroccan-spiced chickpeas is just...magic.
And if you're not veggie, you simply must have a side of the lamb sausage. No ifs, ands or buts allowed. No, sirree.
![]() |
| Consider a NoSQL solution such as Redis the next time you need to implement search... |
Last week I demonstrated how to setup autocomplete in a new Rails 3.1 app using the Soulmate gem, from SeatGeek. Soulmate uses Redis to cache all of the autocomplete phrases in memory, providing lightning fast query results. While autocomplete is a very useful feature and a common web site design element, what really interests me about Soulmate are the ideas and detailed techniques behind how it uses a NoSQL Redis database to implement autocomplete search…
Awesome cycling just got a bit more expensive.
$ thumping the Rupee
Awesome cycling just got a bit more expensive.
$ thumping the Rupee
Last year, on the lookout for a way to bring brussels sprouts into the Thanksgiving meal (we've always been more of a green bean family), I stumbled across Zak Pelaccio's (he of Fatty Crab and Fatty 'Cue) recipe for the most obscene sprouts ever conceived. Bascially, you render the fat out of half a pound of bacon, then cook two pounds of sprouts in it - oh, and then you add heavy cream and good maple syrup, just in case you were worried that the recipe wasn't quite festive enough.
I know.
I tested the recipe first on a few willing victims at Thanksgiving, then pulled it out again for Christmas dinner at Nick & Louisa's in Austin. When this year's feast rolled around, I petitioned my Aunt Cathi, the hostess, for a spot on the menu for these little balls of goodness. Permission was granted, and the sprouts rode again.
I've tweaked the original a bit; Pelaccio added chestnuts to his, but since chestnuts aren't my most favorite nut - and are, in fact, a pain in the ass to roast and peel - I've left them out. As you all know, I like a bit of acid and heat with my rich flavors, so I've added a bit of red pepper for kick.Need I say that they've been requested for the upcoming Christmas feast? I'll say it any case: these will be appearing on my table at least one more time in 2011, and I think you should give them a try as well.
Queenie's Holiday Sprouts
Adapted from Zak Pelaccio
1/2 pound applewood bacon, cut into 1/4 inch batons
2 pounds brussels sprouts, trimmed and sliced in half lengthwise
Sea salt
3 cloves garlic, minced
3 sprigs thyme
1 tsp. dried red pepper
3/4 cup cream
Scant 1/4 cup good maple syrup
Juice of half a lemon
In a large skillet set over medium-high heat, render the fat out of the bacon until it is nearly crispy. Remove bacon to a plate lined with paper towels, but leave the fat in the pan.
Add the sprouts to the pan, season with a generous amount of sea salt, and saute until they begin to get brown, about 4 minutes or so. Add the garlic, thyme and red pepper and saute until the garlic turns golden, another 2 to 3 minutes.
Reduce the heat to medium and add the cream. Cook gently until the cream has reduced by half; it will also turn a golden brown, thanks to the goodness on the bottom of the pan. Add the maple syrup and the reserved bacon to the pan, and cook for a few minutes. Squeeze the lemon over the sprouts. Taste for seasoning (add more salt and red pepper as needed) and serve.
Serves 8 as a side dish.
Red Bull – Mountain Bike Chronicles Season 1
Q: What is a Monday Bicycling Movie nite?
Well, there is a lot of awesome bicycling happening all around the world. We intend to share some of these with you every monday.
We start around 7:30pm and wrap up in an hour.
Today, 28 November
Time – 7:30pm
Where – BumsOnTheSaddle
Yup. We are watching 45 mins of Red Bull Mountain Bike Chronicles
1. Why – Monday’s are boring. We want to spice up your life.
2. BYOB event – so BYOB please.
3. Everyone is welcome.
Red Bull – Mountain Bike Chronicles Season 1
Q: What is a Monday Bicycling Movie nite?
Well, there is a lot of awesome bicycling happening all around the world. We intend to share some of these with you every monday.
We start around 7:30pm and wrap up in an hour.
Today, 28 November
Time – 7:30pm
Where – BumsOnTheSaddle
Yup. We are watching 45 mins of Red Bull Mountain Bike Chronicles
1. Why – Monday’s are boring. We want to spice up your life.
2. BYOB event – so BYOB please.
3. Everyone is welcome.
I follow some 80 odd people/ news sources on my twitter account. For a while I wondered which of these sources are most active on twitter. I picked a simple metric '# of status messages posted to twitter' as the measure of activity. Using R I quickly wrote a program to generate my top 10 most active twitter sources.
Here is the bar plot of the result
## Prerequisite: Install twitteR package 'install.packages(twitteR)
## load twitteR package
library(twitteR)
##get handle to a twitteR user object (in this case for user d_lalit
tuser <- getUser('d_lalit')
##get list of friends of d_lalit
tfriends <- userFriends(tuser)
##create an array to store the name and number of status messages for each friend
friendsCount <- length(tfriends)
friendsName <- character(friendsCount)
friendsMsgCount <- numeric(friendsCount)
for (i in 1:friendsCount) {
friendsName[i] <- tfriends[[i]]$screenName
friendsMsgCount[i] <- as.numeric(tfriends[[i]]$statusesCount)
}
## prepare a sortedlist and extract top 10 values from the list
sortedlist <- sort(friendsMsgCount, index.return = TRUE, decreasing=TRUE)
top10friendsName <- character(10)
top10friendsMsgCount <- numeric(10)
for (i in 1:10) {
top10friendsName[i] <- friendsName[sortedlist$ix[[i]]] ## index is stored under ix
top10friendsMsgCount[i] <- as.numeric(sortedlist$x[[i]])
}
## plot the chart
barplot(top10friendsMsgCount, width = 0.25, names.arg = top10friendsName, horiz=FALSE, main="Twitter friends by activity count", ylab="Number of status messages", xlab="twitter friends", space=0.2, density=50, angle=45, cex.names=0.7)
Check out the other pics of our bicycling space
Check out the other pics of our bicycling space
Pushed inverted waterfall chart implementation with Highcharts to Github @inverted-waterfall-chart
e.g. Zero Gap, i.e. Planned Savings = Actual Savings
Positive Gap, i.e. Actual Savings > Planned Savings
Negative Gap, i.e. Actual Savings < Planned Savings
![]() |
| Fast autocomplete with Soulmate can help users fall in love with your Rails app |
Back in February the SeatGeek team open sourced a gem they call Soulmate that implements autocomplete using a Redis back end. “Soulmate finishes your sentences” as they say on their Github readme page. You can see it in action on SeatGeek.com. Soulmate is very useful: many of us need type ahead search behavior and using Redis is a great way to make it fast and snappy. But more importantly, Soulmate is a great example of how to create an index in Redis ahead of time, allowing for very fast lookups later. Take a few minutes to learn how Soulmate works; chances are you’ll be able to use the same approach in your own app with a completely different data set…
They Bangalore Brevets are all ready to kickoff again. Time to dust off your touring bike and enjoy some kickass long rides!
The first brevet of the 2011-2012 season, the Huliyurdurga 200km BRM takes us through what was erstwhile big cat territory, the word “huli” refers to tigers! The route is a quiet one visiting Magadi, the erstwhile capital, two state forests, Huliyurdurga, Maddur, Ramanagara and Manchanbele before returning to Bangalore. Except for the stretch between Maddur and Ramanagara on Mysore road, the route avoids busy roads, and the ride is along quiet and green roads.
Note that this is a rolling route with steep ascents and descents.
This is an ACP sanctioned brevet ride, and must be completely self-supported. The ride has to be finished within 13.5 hrs. This is not a competitive ride.
Date: Nov 26, 2011
Time: 6AM start. Registration formalities begin 5.30AM
Start: Indian Institute of Science Gymkhana Gate, Yeshwantpur
End: Indian Institute of Science, A-Mess Gate/Kendriya Vidyalaya Gate, Mathikere Road
Distance: 200 km
Time limit: 13.5 hours
More Details – www.BangaloreBrevets.in
They Bangalore Brevets are all ready to kickoff again. Time to dust off your touring bike and enjoy some kickass long rides!
The first brevet of the 2011-2012 season, the Huliyurdurga 200km BRM takes us through what was erstwhile big cat territory, the word “huli” refers to tigers! The route is a quiet one visiting Magadi, the erstwhile capital, two state forests, Huliyurdurga, Maddur, Ramanagara and Manchanbele before returning to Bangalore. Except for the stretch between Maddur and Ramanagara on Mysore road, the route avoids busy roads, and the ride is along quiet and green roads.
Note that this is a rolling route with steep ascents and descents.
This is an ACP sanctioned brevet ride, and must be completely self-supported. The ride has to be finished within 13.5 hrs. This is not a competitive ride.
Date: Nov 26, 2011
Time: 6AM start. Registration formalities begin 5.30AM
Start: Indian Institute of Science Gymkhana Gate, Yeshwantpur
End: Indian Institute of Science, A-Mess Gate/Kendriya Vidyalaya Gate, Mathikere Road
Distance: 200 km
Time limit: 13.5 hours
More Details – www.BangaloreBrevets.in
Rails has so much support for testing built into itself that its rare I come up with something that’s hard to test but HTTP headers is not easy. Normally you don’t have to worry about HTTP headers as they’re set by the browser and you don’t do much with them. Recently I was working on an application where each user has an IP whitelist and they are only allowed to come from their whitelisted IP addresses. This isn’t as crazy as it sounds since the app is in a corporate environment and the users will all be coming from their corporate networks.
Basically this means our authentication method needs 3 pieces of information
What makes this interesting is that the first two are input by the user but the ip address comes from the browser and network. Writing an RSpec unit test or Cucumber scenario to test user parameters (username and password) is something we’ve all done before but today I’m going to talk about how you can also test the IP address in a header.
Before we look at how to test this let’s take a look at the implementation of our SessionController.
class SessionsController < ApplicationController
def new
@session = Session.new
end
def create
remote_ip_address = request.headers['X-Forwarded-For'] || request.headers['REMOTE_ADDR']
@session = Session.create(params[:username], params[:password], remote_ip_address)
if @session.valid?
session[:current_user] = @session.user
redirect_to root_url
else
flash.now[:error] = 'Unable to authenticate. Please try again'
render :new
end
end
def destroy
session[:current_user] = nil
redirect_to session
end
end
These three actions provide login and logout.
new displays the login form with username & password fieldscreate uses the username and password from the form as well as the ip address to create a session (i.e. authenticate). In case the request hops through some proxy servers we use the X-Forwarded-For header to get the source IP and not the proxy’s IP.destroy users need to log out (but we wont talk about that anymore here)This works, but you shouldn’t trust me. We need tests around the create action!
Our Controller Spec needs to pass all 3 pieces of information (username, password & ip address) to the controller. Passing the username and password is pretty standard and something I’m sure you’ve done before. They come from a form so we pass them as a hash in the second argument to post.
post :create, {:username => 'alex', :password => 'secret'}
Unfortunately we can’t pass the IP the same way because the post method in ActionController::TestCase doesn’t support passing headers in (but it does take the session or flash - that’s interesting to remember for some other time).
def post(action, parameters = nil, session = nil, flash = nil)
process(action, parameters, session, flash, "POST")
end
If we keep looking around it turns out the ActionDispatch::TestRequest object has a nice convenience method that lets us specify the remote_addr directly.
def remote_addr=(addr)
@env['REMOTE_ADDR'] = addr
end
If we add a line to our spec we can handle the case where the IP comes in the REMOTE_ADDR HTTP header.
request.remote_addr = '192.168.1.100'
post :create, {:username => 'alex', :password => 'secret'}
We still need to deal with the X-Forwarded-For case. While Rails doesn’t give us a convenience method, by looking at the implementation of the remote_addr= method we can see how to set this header ourselves.
request.env['X-Forwarded-For'] = '192.168.1.100'
post :create, {:username => 'alex', :password => 'secret'}
Putting it all together we end up with a controller spec that looks like this.
require 'spec_helper'
describe SessionsController do
describe '#create' do
describe 'successfully' do
let(:alex) { mock }
let(:valid_session) { mock(:valid? => true, :user => alex )}
before do
Session.should_receive(:create).with('alex', 'secret', '192.168.1.100').and_return(valid_session)
end
describe 'using REMOTE_ADDR' do
before do
request.remote_addr = '192.168.1.100'
post :create, {:username => 'alex', :password => 'secret'}
end
it { should redirect_to root_path }
it { should set_session(:current_user).to(alex)}
end
describe 'using X-Forwarded-For' do
before do
request.remote_addr = '172.16.254.1'
request.env['X-Forwarded-For'] = '192.168.1.100'
post :create, {:username => 'alex', :password => 'secret'}
end
it { should redirect_to root_path }
it { should set_session(:current_user).to(alex)}
end
end
describe 'unsuccessfully' do
let(:invalid_session) { mock(:valid? => false) }
before do
Session.should_receive(:create).with('alex', 'secret', '192.168.1.100').and_return(invalid_session)
end
describe 'using REMOTE_ADDR' do
before do
request.remote_addr = '192.168.1.100'
post :create, {:username => 'alex', :password => 'secret'}
end
it { should render_template :new }
end
describe 'using X-Forwarded-For' do
before do
request.remote_addr = '172.16.254.1'
request.env['X-Forwarded-For'] = '192.168.1.100'
post :create, {:username => 'alex', :password => 'secret'}
end
it { should render_template :new }
end
end
end
end
To sum up we can
pass parameters as a hash in the post method
post :create, {:username => 'alex', :password => 'secret'}
set the remote_addr on the request with a convenience method
request.remote_addr = '192.168.1.100'
et the X-Forwarded-For directly on the requests’s environment hash
request.env['X-Forwarded-For'] = '192.168.1.100'
We face a similar issue when writing our cucumber scenarios - its easy to pass the username and password but harder to pass the IP address. The solution turns out to be similar but not quite exactly the because our Cucumber steps will use Capybara instead of ActionController::TestCase directly. Before we look into how to implement the steps, let’s write the feature we want which will help us define the steps we need.
Feature: Authentication of a user
In order to ensure a really secure application
As a user
I want my IP address to be validated during login
Background:
Given the following user exists:
| username | password | company |
| alex | secret | ip_address: 192.168.1.100 |
Scenario: Successful log in
Given I am connecting from ip "192.168.1.100"
When I log in as "alex" with password "secret"
Then I should be on the home page
Scenario: Successful log in with X-Forwarded-For header
Given I am connecting from ip "192.168.1.100" behind a proxy
When I log in as "alex" with password "secret"
Then I should be on the home page
Scenario: Failed log in from wrong IP
Given I am connecting from ip "172.16.254.1"
When I log in as "alex" with password "secret"
Then authentication should have failed
Scenario: Failed log in from wrong IP behind a proxy
Given I am connecting from ip "172.16.254.1" behind a proxy
When I log in as "alex" with password "secret"
Then authentication should have failed
We immediately realize we don’t know how to write the first step
Given /^I am connecting from ip "([^"]*)"$/ do |ip_address|
pending # How do we set the IP Address???
end
To figure this out we need to dig into how capybara works.
We don’t call post in ActionController::TestCase directly instead letting capybara do it for us. To see what capybara is doing we can skip that step and implement the login step
Given /^I am connecting from ip "([^"]*)"$/ do |ip_address|
# do nothing for now
end
When /^I log in as "([^"]*)" with password "([^"]*)"$/ do |name, password|
visit(new_session_path)
fill_in('User name', :with => name)
fill_in('Password', :with => password)
click_button('Log In')
end
and edit the SessionsController to show us the stack trace.
class SessionsController < ApplicationController
def create
raise caller.inspect
end
end
The stack trace is very big but if we look closely, somewhere in the middle of it we see lines below that show how capybara uses the rack-test gem to submit our form.
~/.rvm/gems/ruby-1.8.7-p334/gems/rack-test-0.6.1/lib/rack/test.rb:66:in `post'
~/.rvm/gems/ruby-1.8.7-p334/gems/capybara-1.1.2/lib/capybara/rack_test/browser.rb:62:in `send'
~/.rvm/gems/ruby-1.8.7-p334/gems/capybara-1.1.2/lib/capybara/rack_test/browser.rb:62:in `process'
~/.rvm/gems/ruby-1.8.7-p334/gems/capybara-1.1.2/lib/capybara/rack_test/browser.rb:27:in `submit'
~/.rvm/gems/ruby-1.8.7-p334/gems/capybara-1.1.2/lib/capybara/rack_test/form.rb:64:in `submit'
... more lines omitted...
~/.rvm/gems/ruby-1.8.7-p334/gems/capybara-1.1.2/lib/capybara/node/actions.rb:38:in `click_button'
Looking at the Rack::Test#post method we see something similar to what we saw before in ActionController::TestCase but its not quite identical. It takes the env as a parameter so we need to figure out how to inject our header in there.
def post(uri, params = {}, env = {}, &block)
env = env_for(uri, env.merge(:method => "POST", :params => params))
process_request(uri, env, &block)
end
Following the stack trace up we see the env passed into Rack::Test::Session.post comes from Capybara::RackTest::Browser and it turns out that env is computed in the Capybara::RackTest::Browser#env method.
def options
driver.options
end
def env
env = {}
begin
env["HTTP_REFERER"] = last_request.url
rescue Rack::Test::Error
# no request yet
end
env.merge!(options[:headers]) if options[:headers]
env
end
The key is in the line env.merge!(options[:headers]) if options[:headers] and those options are delegated to the driver. Now we know how to inject our IP address onto the driver’s options.
Given /^I am connecting from ip "([^"]*)"$/ do |ip_address|
page.driver.options[:headers] = {'REMOTE_ADDR' => ip_address}
end
Putting it all together we can write all our steps
Given /^I am connecting from ip "([^"]*)"$/ do |ip_address|
page.driver.options[:headers] = {'REMOTE_ADDR' => ip_address}
end
Given /^I am connecting from ip "([^"]*)" behind a proxy$/ do |ip_address|
page.driver.options[:headers] = {'X-Forwarded-For' => ip_address}
end
When /^I log in as "([^"]*)" with password "([^"]*)"$/ do |name, password|
visit(new_session_path)
fill_in('User name', :with => name)
fill_in('Password', :with => password)
click_button('Log In')
end
Then /^I should be on the home page$/ do
URI.parse(current_url).path.should == root_path
end
Then /^authentication should have failed$/ do
page.text.should include 'Unable to authenticate. Please try again'
end
Now the scenarios we wrote before all pass.
To sum up
capybara handles form submission superbly with
fill_in('User name', :with => name)
click_button('Log In')
we can set any HTTP header in capybara with
page.driver.options[:headers] = {'REMOTE_ADDR' => ip_address}
Since we’re testing the IP logic at both the unit level with RSpec and integration level with Cucumber and Capybara we can be pretty sure it’s all going to work correctly.
I'm kicking off this season's gift guide series with a bang: a collection of the most brightly colored bits and bobs on offer. See, in the dreary doldrums of winter in the Northeast (which follow hot on the heels of the holiday season), everyone needs a little cheering up. For some, this comes in the form of one of those vitamin D sun lamps; for me, it comes in a jazzy iPhone case and bright pink lamps.
People tend to think of bright colors as a girlie thing, but I happen to think that men could use a little neon in their life as well. Maybe help him start small, with a neon pen or two, or introduce a bright yellow Baggu into the grocery shopping rotation.
Up next, books galore!
The gifts, clockwise from top left: Neon enamel pens ($20 each), chevron iPhone case ($39.99), Baggu bag ($8), Dents suede gloves ($31.45), table lamp ($150.70), Swarovski beaded friendship bracelets ($65 each).
image credit – Szymon Nieborak
Q: What is a Monday Bicycling Movie nite?
Well, there is a lot of awesome bicycling happening all around the world. We intend to share some of these with you every monday.
We start around 7:30pm and wrap up in an hour.
Today, 21st November
Time – 7:30pm
Where – BumsOnTheSaddle
Excerpt
The long awaited full film – Being Free – is here!
This summer Nico Turner has been working hard travelling across the UK and Europe to produce this master piece. Anyone with any experience of film making knows just how hard it is to create something of this standard purely off your own back. Nico rises to the challenge every time and reminds us what dedication is all about. He is behind the camera for every single shot and has spent hours in front of a monitor editing for your viewing pleasure!
Yup. We are watching 45 mins of Being Free
1. Why – Monday’s are boring. We want to spice up your life.
2. BYOB event – so BYOB please.
3. Everyone is welcome. Really.
image credit – Szymon Nieborak
Q: What is a Monday Bicycling Movie nite?
Well, there is a lot of awesome bicycling happening all around the world. We intend to share some of these with you every monday.
We start around 7:30pm and wrap up in an hour.
Today, 21st November
Time – 7:30pm
Where – BumsOnTheSaddle
Excerpt
The long awaited full film – Being Free – is here!
This summer Nico Turner has been working hard travelling across the UK and Europe to produce this master piece. Anyone with any experience of film making knows just how hard it is to create something of this standard purely off your own back. Nico rises to the challenge every time and reminds us what dedication is all about. He is behind the camera for every single shot and has spent hours in front of a monitor editing for your viewing pleasure!
Yup. We are watching 45 mins of Being Free
1. Why – Monday’s are boring. We want to spice up your life.
2. BYOB event – so BYOB please.
3. Everyone is welcome. Really.
Hey, cats and kittens! Just wanted to let you know that my gift guides for the 2011 holiday season will be coming your way this week. I've got three installments this time around - brights for those of you craving summer, books for those of you who want nothing more than to curl up with a good one, and the makings of the best boozy, cold-weather picnic ever.
Get ready, because here comes fun! (If, by fun, you mean holiday shopping ideas. Because that's what I mean.)
And, if you simply must have it, Oscar's blinky nose can be found here.
Our last off road race of this season!
Race stats, click for more details
Location – Hesarghatta
Driving directions – http://goo.gl/ND7By a Dummies Guide to reach Hesarghatta
Race route – http://goo.gl/SLNhT
Start time – 0830 IST
Distance – ~4 km x 4 laps
Since this is the last off road race of the season we thought it would be a good idea to have a lot more than just a kickass race
We will have the usual ambulance and first aid kit.
Please contribute to the Vit M box. This is very essential to keep running the races. We think 200 INR per biker makes our Vit M kitty feel like it has something inside.
Our last off road race of this season!
Race stats, click for more details
Location – Hesarghatta
Driving directions – http://goo.gl/ND7By a Dummies Guide to reach Hesarghatta
Race route – http://goo.gl/SLNhT
Start time – 0830 IST
Distance – ~4 km x 4 laps
Since this is the last off road race of the season we thought it would be a good idea to have a lot more than just a kickass race
We will have the usual ambulance and first aid kit.
Please contribute to the Vit M box. This is very essential to keep running the races. We think 200 INR per biker makes our Vit M kitty feel like it has something inside.
You can find my article this week over on rubysource.com.
I’ve started to teach my kids to program. I figured I build websites professionally and it’d be a fun way for me to share what I do and help supplement their learning. And it was something they expressed interest in not something I was pushing. I suggested we build our own small version of facebook or twitter. Very quickly I learned two truths
Okay. I’ve never built a game before after a little digging there are plenty of tools in the open source world and many built on Ruby. We’re currently experimenting with three different tools/technologies.
I first came across Shoes several years ago and was blown away. It was originally written by why and is now maintained by Team Shoes on github. “Shoes is the best little DSL for cross-platform GUI programming there is. It feels like real Ruby, rather than just another C++ library wrapper”
Writing a Shoes app feels just like writing a Ruby app (it is Ruby!). The best analogy I can use is that what Rails does for websites, Shoes does for GUI apps.
If you want to create a blue rectangle on a page, here’s your app
Shoes.app do
fill blue
rect :top => 25, :left => 50, :height => 75, :width => 150
end

We can make it a bit more interactive and allow the user to move our rectangle around with the arrow keys and display the current coordinates
Shoes.app do
fill blue
@player = rect :top => 25, :left => 50, :height => 75, :width => 150
@current_coordinates = para "(#{@player.left}, #{@player.top})"
keypress do |key|
@player.left += 10 if key == :right
@player.left -= 10 if key == :left
@player.top += 10 if key == :down
@player.top -= 10 if key == :up
@current_coordinates.replace "(#{@player.left}, #{@player.top})"
end
end

We’re not limited to blue rectangles. We can replace it with an image
Shoes.app do
@player = image 'images/Starfighter.png', :top => 25, :left => 50
@current_coordinates = para "(#{@player.left}, #{@player.top})"
keypress do |key|
@player.left += 10 if key == :right
@player.left -= 10 if key == :left
@player.top += 10 if key == :down
@player.top -= 10 if key == :up
@current_coordinates.replace "(#{@player.left}, #{@player.top})"
end
end

We’re writing Ruby in a fairly natural way. Shoes just gives us GUI methods like rect to create a rectangle or para to create a paragraph. Because this is Ruby, as your Shoes app gets more complex you can create classes and methods to organize and keep it manageable just as you would in any other app.
There are all sorts of great resources out there including
Gosu is a gaming library so while Shoes lets us build any sort of GUI apps this is seemed like it might be a better fit since we’re interested in gaming. Luckily there’s a gem that wraps up the Ruby interface (Gosu can be used from C++ or Ruby).
gem install gosu
If we want to build a similar game to what we did in Shoes with a play we move around via the arrow keys we need to subclass the Gosu::Window class.
require 'rubygems'
require 'gosu'
class Player
def initialize(window)
@image = Gosu::Image.new(window, "media/Starfighter.png", false)
@x, @y = 125, 50
@angle = 0.0
end
def draw
@image.draw_rot(@x, @y, 0, @angle)
end
end
class GameWindow < Gosu::Window
def initialize
super(640, 480, false)
self.caption = "Gosu Tutorial Game"
@player = Player.new(self)
end
def draw
@player.draw
end
end
window = GameWindow.new
window.show
And we see a window with a player that looks like a starship

Its not too hard to make it move by overriding the update method in our window class
require 'rubygems'
require 'gosu'
class Player
attr_accessor :x, :y
def initialize(window)
@image = Gosu::Image.new(window, "media/Starfighter.bmp", false)
@x, @y = 75, 50
@angle = 0.0
end
def draw
@image.draw_rot(@x, @y, 0, @angle)
end
end
class GameWindow < Gosu::Window
def initialize
super(400, 300, false)
self.caption = "Our Game"
@player = Player.new(self)
@current_coordinates = Gosu::Font.new(self, Gosu::default_font_name, 20)
end
def update
@player.x -= 10 if button_down? Gosu::KbLeft
@player.x += 10 if button_down? Gosu::KbRight
@player.y += 10 if button_down? Gosu::KbDown
@player.y -= 10 if button_down? Gosu::KbUp
end
def draw
@player.draw
@current_coordinates.draw("(#{@player.x}, #{@player.y})", 10, 10, 0, 1.0, 1.0, 0xffffff00)
end
end
window = GameWindow.new
window.show

This example can be extended into a full Asteroids like like game where your ship has inertia. You should look at the source or an explanation on the gosu site.
There are all sorts of great resources out there including
| Falling Blocks | or | CptnRuby |
![]() |
![]() |


Even though we’re still writing Ruby, Gosu feels more like C++ Windows development I used to do long long time ago. I’m not sure if that’s inevitable and need to keep using Gosu to find out.
The last framework we’ve been working with is pretty different. GameSalad advertises it lets you “Create games for iPhone, iPad, Android, Mac, and HTML5. No coding required.”
It follows a model similar to what Adobe Flash uses where you have Scenes containing Actors. You write your programs in a visual editor by dragging and dropping Actors onto Scenes, Rules onto Actors and Behavior onto Rules. For instance if we have a starship actor and we drop these rules onto it

We will get our familiar spaceship that can move left and right

GameSalad is the least familiar to me but seems to be easiest for my kids to start working on. Not having to write any “code” or “do programming” makes it much easier to get started. It also can create iPhone or iPad games and I would never dream of exposing my kids to Objective-C.
We’ve started experimenting with all three of these tools and so far are having fun with all three. Hopefully we’ll figure out what works for us and perhaps try to write about it again in a few months.
After writing this I came across a recent NY Times article Programming for Children, Minus Cryptic Syntax and Scratch also sounds interesting so I may have to look into that sometime too.
Every Monday Bicycling Movie nite – we intend to watch a biking movie every monday evening.
Start around 7:30pm and wrap up in an hour.
Today, 14th November
Time – 7:30pm
Where – BumsOnTheSaddle
After two seasons of following the Cervelo TestTeam, Joseph Finkleman and Booker Sim now follow Team Garmin-Cervélo and capture the human passion and beauty of cycling.
With their all-access passes, they show you what conventional race footage fails to capture: everything “beyond” the peloton.
Yup. We are watching 45 mins of Beyond the Peloton
1. Why – Monday’s are boring. We want to spice up your life. 2. BYOB event – so BYOB please. 3. Everyone is welcome. Really.
Every Monday Bicycling Movie nite – we intend to watch a biking movie every monday evening.
Start around 7:30pm and wrap up in an hour.
Today, 14th November
Time – 7:30pm
Where – BumsOnTheSaddle
After two seasons of following the Cervelo TestTeam, Joseph Finkleman and Booker Sim now follow Team Garmin-Cervélo and capture the human passion and beauty of cycling.
With their all-access passes, they show you what conventional race footage fails to capture: everything “beyond” the peloton.
Yup. We are watching 45 mins of Beyond the Peloton
1. Why – Monday’s are boring. We want to spice up your life. 2. BYOB event – so BYOB please. 3. Everyone is welcome. Really.
Go by Bike!
Sri Harsha has a good writeup about his bicycle commute (and his earlier post). Thank you for the kind words about BumsOnTheSaddle Harsha! We love you too!
A bicycle commute is always awesome – fast, fun and cheap-er
Here’s how you can ensure a fun commute
Go by Bike!
Sri Harsha has a good writeup about his bicycle commute (and his earlier post). Thank you for the kind words about BumsOnTheSaddle Harsha! We love you too!
A bicycle commute is always awesome – fast, fun and cheap-er
Here’s how you can ensure a fun commute
Sometimes I think there's nothing in the house for breakfast, and then I remember that I have eggs, scallions, a tomato and half an avocado. What's better than that?
Answer: the Sriracha I squirted all over it after I snapped this photo.
Randonneuring is a non-competitive, self-supported, long-distance cycling activity.
Populaires allow people to sample randonneuring over shorter distances, typically less than 200km.
IISC Randonneurs proudly present the Arkavathi 150
Date: November 12, 2011, 06:00 AM
Start: Indian Institute of Science Gymkhana Gate, Yeshwantpur
End: Indian Institute of Science, A-Mess Gate/Kendriya Vidyalaya Gate, Mathikere Road
Distance: 147 km
Time limit: 10 hours
A lot more info on the IISC Randonneurs page. Way to go guys.
I've always really wanted to love pumpkin bread. In theory, it should be an easy thing for me to do. I'm a big fan of the pound cake/quick bread genre, and I really love pumpkin-spiked baked goods, particularly scones and pie. It should be an easy sell. But, in my experience, most recipes for pumpkin bread result in overly-sweet, overly-oily, cloying messes of a loaf.
This year, I decided to take charge of the pumpkin loaf. No longer would I be a slave to such sub-par use of one of nature's most delicious ingredients. It was time for a revolution.
As a starting point, I used this recipe from Bon Appétit. I'd tried it before, and been pleased with the texture, but disappointed in the flavor. It was too sweet and not nearly spicy enough. After all, what is the point of baking with pumpkin if you're not going to exercise a moderately heavy hand with the ginger, cloves and cinnamon? What is autumn if not an excuse to clear out the spice cabinet?
And so I got to work. Out went one of the three cups of sugar, and, for good measure, I swapped one of the remaining two for half a cup each of dark and light brown sugar. After all, pumpkin and molasses (the "brown" in brown sugar) play pretty well together. In went extra cinnamon and cloves, freshly grated nutmeg stood in for the powdered stuff, and ginger was added to the mix.
The result is a pumpkin loaf that - I think - successfully bridges the gap between pumpkin bread and gingerbread. It's spicy and just a bit sweet, moist and fragrant. It made my apartment smell heavenly for days, and if you make it in these adorable little mini loaf pans, it just might be the best host or hostess gift the holiday season ever saw. Except for a bottle of bourbon.
Spiced Pumpkin Bread
Adapted from Bon Appétit
Butter for greasing the pans
3 cups all purpose flour, plus a bit for flouring the pans
2 tsp. ground cloves
3 tsp. ground cinnamon
1 tsp. freshly grated nutmeg
1 tsp. ginger
1 tsp. baking soda
1/2 tsp. baking powder
1/2 tsp. kosher salt
1 cup canola oil
1 cup granulated sugar
1/2 cup light brown sugar
1/2 cup dark brown sugar
3 large eggs
1 16-ounce can of pure, pureed pumpkin
1 tsp. vanilla
Pre-heat the oven to 350 degrees Fahrenheit. Butter and flour two standard, 9x5x3 inch size (or four mini) loaf pans. If using mini loaf pans, place them on a cookie sheet.
In a large bowl, sift together the flour, spices, baking soda and baking powder. Stir the salt in with a fork. In another large bowl, mix together the sugars and oils, then add the eggs, pumpkin and vanilla. If you have any lumps from the brown sugars, use a large whisk to help dissolve them into the mixture.
Add the flour mixture to the wet ingredients in two additions, mixing well with a spatula or wooden spoon after each. Divide the batter evenly between the pans, then place in the oven and bake until a tester inserted into the cakes comes out clean - about an hour for mini loaves, and 70 minutes for the larger loaves. I'd also recommend rotating the loaves about halfway through baking - spinning them front to back and switching baking racks, if you're using two.
Cool in the pans for about 30 minutes, then run a butter knife around the edges of the loaves. Invert onto a cooling rack to cool completely. Eat immediately or wrap tightly in plastic wrap and store at room temperature for up to four days.
Makes two standard loaves or four mini loaves.
# ruby developer packages
sudo apt-get install ruby1.8-dev ruby1.8 ri1.8 rdoc1.8 irb1.8
sudo apt-get install libreadline-ruby1.8 libruby1.8 libopenssl-ruby
# nokogiri requirements
sudo apt-get install libxslt-dev libxml2-dev
sudo gem install nokogirisudo apt-get install libmysql-ruby libmysqlclient-dev
sudo gem install mysql

In 2008 I thought RSS was an awesome way to stay abreast of what’s going on, but now its 2011 and I find myself using Twitter more often than Google Reader to find new and interesting articles people have written. Readers tweet and retweet articles they find interesting which seems a lower barrier than leaving an “I like this” comment. As an author Twitter also gives you some idea of who is reading your posts and a way to connect with them.
Back in 2008 I created a blog aggregator site http://waywework.it to group the all the people I work with and promote others to share their thoughts. I was so excited I even wrote an article about it.
Now that its 2011, I’ve been asking myself how could I update http://waywework.it for the twitter world of today?
I decide that if we’re going to follow people on twitter that’s what my site should facilitate. When new posts come in it should tweet them letting you see them if you follow @WayWeWorkIT.
Once I had this I added the twitter gem to my application. I have to give a shout out John Nunemaker for writing this fantastic gem which made my task so simple.
In the Gemfile
gem 'twitter'
I created a new twitter account @WayWeWorkIT and registered an application at https://dev.twitter.com/apps so I had my OAuth and access tokens.
The only trick was I had to go Application Settings tab and configure it for Read and Write access then regenerate the tokens.
Now that I had the keys and tokens from twitter I had to tell my application to use them without hardcoding them in my code. This took two steps. First, configuring the app to read the tokens from the environment in config/initializers/twitter.rb. Yes I am somewhat paranoid about accidentally tweeting from development but that if Rails.env.production? should save me.
if Rails.env.production?
Twitter.configure do |config|
config.consumer_key = ENV['TWITTER_CONSUMER_KEY']
config.consumer_secret = ENV['TWITTER_CONSUMER_SECRET']
config.oauth_token = ENV['TWITTER_OAUTH_TOKEN']
config.oauth_token_secret = ENV['TWITTER_OAUTH_TOKEN_SECRET']
end
end
Secondly, setting the tokens on the heroku environment (I typed the real tokens instead of the XXXXXXXX’s).
$ heroku config:add TWITTER_CONSUMER_KEY=XXXXXXXX
$ heroku config:add TWITTER_CONSUMER_SECRET=XXXXXXXX
$ heroku config:add TWITTER_OAUTH_TOKEN=XXXXXXXX
$ heroku config:add TWITTER_OAUTH_TOKEN_SECRET=XXXXXXXX
We can test it out (after deploying with git push heroku)
$ heroku console
>> Twitter.tweet('http://waywework.it aggregates blog articles')
=> # some big object returned
>> Twitter.user_timeline('wayweworkit').first.text
=> "http://t.co/FCmUQdc3 aggregates blog articles"
Great we just tweeted our first tweet for the world to see.
The app periodically scans the rss feeds it tracks and when it sees a new post it creates it in the app’s database.
First we add a twitter_username to each feed we’re tracking
class AddTwitterUsernameToFeeds < ActiveRecord::Migration
def change
add_column :feeds, :twitter_username, :string
end
end
Then, add an after_create callback to tweet each time we create a new post.
class Post < ActiveRecord::Base
after_create :tweet
delegate :twitter_username, :to => :feed
def twitter_username_with_at_sign
"@#{feed_twitter_username || 'WayWeWorkIT'}
end
# See https://dev.twitter.com/docs/tco-link-wrapper/faq#Will_t.co-wrapped_links_always_be_the_same_length
# We should query instead of hardcoding 20
def short_url_length
20
end
def tweet
if Rails.env.production?
non_title_part_of_tweet = " #{'x'*short_url_length} via #{twitter_username_with_at_sign}"
max_title_length = 140 - non_title_part_of_tweet.length
tweet = "#{title.truncate(max_title_length)} #{url} via #{twitter_username_with_at_sign}"
Twitter.update(tweet)
end
end
end
Again with the “if Rails.env.production?” paranoia? You do know that you can never be too paranoid :)
With the twitter gem its one line to tweet Twitter.update(tweet). The rest of it is to shorten the title so twitter’s 140 character limit wont cut off the url or the author’s name.
Once this is in we’ll start seeing tweets like
Go ahead and follow @WayWeWorkIT on twitter and you’ll start seeing these blog posts.
As a half-Jewish girl growing up in the greater New York City area, I ate a lot of Chinese food. Correction: still eat a lot of Chinese food. Some of this is the more authentic dishes to be found mostly in Flushing and Chinatown; most of it is the gleefully Americanized stuff available all over the city, able to summoned with the briefest of phone calls.
Among my lifelong favorites from the latter category are cold sesame noodles. The peanut-y sauce, the chewy noodles, the thinly sliced cucumber and scallions - I love it all. They make an especially great canvas for hot sauce, which only makes them better in my eyes.
But since even I can't justify ordering in Chinese every night, I needed to find a way to satisfy my sesame noodle cravings at a moment's notice. The result? An actually somewhat nutritious version that substitutes julienned squash for the noodles and has a bit of yogurt in the sauce to add heft (and, incidentally, protein). The classic hooks are still there, though - peanut butter, sesame oil, scallions and cucumber all make an appearance. And though it's not often found in Chinese food, I added some fish sauce for funk and awesomeness.
Authentic? No. Tasty? I sure think so. Easy? Empirically so.
Queenie's Sesame "Noodles"
1 large yellow squash or two medium zucchini
2 tbs. Greek yogurt
1 tbs. creamy peanut butter
1 tsp. rice wine vinegar
1 tsp. soy sauce
1/2 tsp. fish sauce
1/4 tsp. Sriracha, plus extra for garnish
1/4 tsp. sesame oil
2 scallions, thinly sliced
1/2 English cucumber, cut in half lengthwise, seeded and cut into 1/4 inch pieces
1 tsp. toasted sesame seeds
Using a mandoline or a julienne peeler, peel the squash (except for the seeds at the core) into long strips. Place in a mesh sieve and sprinkle with a bit of kosher salt. Toss to distribute the salt evenly, then set aside while you prep the sauce.
Combine all remaining ingredients except the scallions, cucumber and sesame seeds in a small bowl. Whisk together with a fork until you have an even, light brown, creamy sauce with no lumps.
Meanwhile, bring a small pot of water to the boil. Add the squash to the pot and cook for 2 minutes. Remove with tongs and place back in the sieve to drain a bit.
Place the drained squash into a large bowl. Add the cucumber and 2/3 of the scallions, followed by a couple spoonfuls of the sauce. Using tongs, toss the "noodles" with the sauce and vegetables until well-combined, adding more sauce until it's as saucy as you want it. Using the tongs, transfer to a small bowl for eating. (You'll want to use tongs, because you'll have a bit of watery sauce left over at the bottom of the mixing bowl.)
Garnish with the remaining scallions, sesame seeds and a bit of Sriracha. Eat immediately.
Serves one, generously.
Hi Folks, If you want to have OAuth in your Rails Application with twitter. OmniAuth is the best gem to use. OmniAuth provides list of Strategies to use many OAuth for your application. Here is the List of Strategies. Showing here a Twitter Strategy for OmniAuth. Twitter uses the OAuth 1.0a flow, you can read about [...]
![]() |
| Bundler 1.1 can help you sort through your gems |
Three weeks ago I explained why Bundler 1.1 will be much faster than Bundler 1.0, which is clearly its most important new feature. However, there are a few new commands and options the Bundler team implemented in version 1.1 that can help you better manage and sort through the gems you have installed on your development computer and servers. Bundler 1.1’s new commands will tell you which gems you can upgrade, and also help keep things clean by deleting gems you no longer need…
Birthday champagne, naturellement.
Jer Thorp walks through his process of how he created a recent visualization for popular science magazine. Part of his process that I find interesting is he says, “This is a really common approach for me to take – building small tools … Continue reading
Socialtext product adoption is way, way up--over 300% YTD. There are many reasons for the phenomenal growth, but in this post I'll focus on one specific factor: our training approach. Some time ago, I had one of those forehead-smacking Ah-Hah...
Installing rbx-require-relative (0.0.5) Unfortunately, a fatal error has occurred.
Please report this error to the Bundler issue tracker at https://github.com/carlhuda/
bundler/issues so that we can fix it. Thanks!/Users/sjain/.rvm/rubies/ruby-1.9.2-p290/
lib/ruby/site_ruby/1.9.1/rubygems/ installer.rb:364:in `ensure_required_ruby_version_met':
rbx-require-relative requires Ruby version ~> 1.8.7. (Gem::InstallError)
Go to Justine's. Order the salade de crevettes and the ratatouille. Thank me later.