Check out the recent post up on Pinkbike’s Tech Tuesday – Rotor Straightening
There are a couple of things we can do regularly to ensure sharp, snappy and spot-on braking.
Step 1: Service the housing
Step 2: Check for wear n tear of the brake pads. If the braking surface is less than an mm thick, replace it.
If the braking surface on the pads is uneven use water proof sandpaper or a fine file to take a thin layer off the brake pads. You could also clean out the pads with the alcohol swabs. This should increase your braking power too.
Check the post on Bike Radar to remore/replace disc brake pads
Step 3: Replace brake cables if you see signs of fraying or rusting. They are cheap to replace and worth it!
Step 4: Clean the Rotors with isopropyl alcohol. Clean out the caliper while you are at it. Get all the gunk out!
Step 5: Insert the brake pads and setup the disc brakes. True the rotor if required – this will not only reduce squealing and ensure better braking but should also increase the life of your brake pads.
If you have a hydraulic system on your bike, you can skip Step 1 and replace it with a hydraulic system bleed the braking feels spongy.
All this should hardly take any time. Especially if done regularly! But it should make a massive difference to your ride and the confidence while braking.
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, 26th September
Time – 7:30pm
Where – BumsOnTheSaddle
We are watching an instructional video on how to tame the trail – 22 MTB handling skills.
1. Why – Monday’s are boring. We want to spice up your life.
2. BYOB event – so BYOB please.
3. Everyone is welcome. Really.
Software as a service (SaaS) is a great thing. I love that other people are providing services and I don’t have to implement them myself. I can use Airbrake for error notifications and even Twitter for communication. It frees me to focus on what’s unique about my app. Its great that they all work with open standards like HTTP, JSON and XML. But what I like even more is not having to think about HTTP, JSON or XML! When writing a Ruby application I want to think about Ruby. The services I really like provide a gem that hides the transport api details and lets me write plain ruby.
Airbrake.notify(ex)Twitter.user_timeline("sferik")If you are creating a service yourself or even using someone else’s service it’s not too hard to create your own client gem. Let’s look at an example how we can do that.
Imagine you’re building a user directory that lets you list users, create users, update users, show users, delete users, you know, the standard RESTFUL actions. For instance we could create a user and list all users like this
[~]$ curl -F 'user[name]'='Mickey Mouse' http://user-directory.example.com/users.json
{"user":{"name":"Mickey Mouse","id":1001}}
[~]$ curl http://user-directory.example.com/users.json
[{"user":{"name":"Mickey Mouse","id":1001}}]
This is great to use from CURL but writing the code to talk http form fields and parse json will get pretty tiring. I’d much rather have a UserDirectory::User object that behaved similarly to an ActiveRecord model. When we’re done we want to be able to have it work this
user = UserDirectory::User.create(:name => 'Jenny', :phone => '867-5309')
# => #<UserDirectory::User:0x10239b0b8 @name="Jenny", @phone="867-5309", @id=1001>
user.name
# => 'Jenny'
user.id
# => 1001
UserDirectory::User.all
# => [ #<UserDirectory::User:0x102375638 @name="Jenny", @phone="867-5309", @id=1001> ]
We’ll want to wrap this client into a gem so it can be reused by many applications. I prefer to use bundler and its bundle gem command to start my gem. I’ll assume you know how to do that - check out this railscast if you’ve never done it before.
We’re going to get started by building a model class to represent the user without actually connecting it to our service yet.
module UserDirectory
class User
include ActiveModel::Validations
validates_presence_of :name
attr_accessor :name, :phone
def initialize(attributes={})
attributes.each do |name, value|
send("#{name}=", value)
end
end
end
end
I hope you didn’t think all model classes had to subclass ActiveRecord::Base! For me a model represents a concept in the application domain and does not have to map to a database table!
The magic in here is that we’re mixing in the ActiveModel::Validations module. This lets us add the same validations we would to a “regular” ActiveRecord model - in this case validates_presence_of :name. When Rails 3.0 came along much of the functionality of ActiveRecord was extracted into ActiveModel which lets you make any ruby object feel like ActiveRecord and as with most other topics Ryan Bates has put together a great railscast.
When we try it out it behaves as we expect.
# A valid user
user = UserDirectory::User.new(:name => 'alex')
# => #<UserDirectory::User:0x12b79fff0 @name="alex">
user.valid?
# => true
# an invalid user
user = UserDirectory::User.new(:phone => '555-1212')
# => #<UserDirectory::User:0x12b78ecf0 @phone="555-1212">
user.valid?
# => false
user.errors
# => #<ActiveModel::Errors:0x12b788f80 @base=#<UserDirectory::User:0x12b78ecf0
# @errors=#<ActiveModel::Errors:0x12b788f80 ...>, @validation_context=nil, @phone="555-1212">,
# @messages=#<OrderedHash {:name=>["can't be blank"]}>>
The next step is to make our model interact with the service using HTTP and JSON. I’m going to be using the HTTParty gem. It is much easier to use than net/http and automatically parses json or xml into a ruby hash for us.
First, we’ll add a create method that tells the service to create a new user as long as we pass our validations and then returns a User instance.
module UserDirectory
class User
# all the existing code and...
def attributes
{ :name => name, :phone => phone }
end
include HTTParty
base_uri 'http://user-directory.example.com'
def self.create attributes
user = new(attributes)
return user unless user.valid?
response = post('/users.json', :body => user.attributes)
raise "#{response.code}: Better error handling please" unless response.success?
self.new(response.parsed_response)
end
end
end
We can do the same for an all method that returns an array of all users stored in the service.
module UserDirectory
class User
# all the existing code and...
def self.all
response = get('/users.json')
raise "#{response.code}: Better error handling please" unless response.success?
response.parsed_response.map do |user_attributes|
self.new user_attributes
end
end
end
end
Let’s try it out.
# No users yet
UserDirectory::User.all
# => []
# Create a user
UserDirectory::User.create(:name => 'alex', :phone => '555-1212')
# => #<UserDirectory::User:0x12c52f0a8 @name="alex", @phone="555-1212">
# Now ask the service again
UserDirectory::User.all
# => [#<UserDirectory::User:0x12b8890d8 @name="alex", @phone="555-1212">]
This is great! We have a class that’s easy to use, behaves like a normal model but actually talks JSON and HTTP to a remote service. We could continue along the same lines to implement the other methods we need like find & destroy but I’m not going to bore you with that here. Instead I’ll switch gears and talk about building a fake service to eliminate the need to have the actual service running during development and testing.
There are a few reasons we want to build a fake service.
How do we create a fake service? Luckily there’s a gem for that! The ShamRack gem intercepts http calls before they leave our app and redirects them to a local Rack App we’ll create. We’ll create a simple sinatra app that implements the UserDirectory Service API and embed it in our gem.
First things first, add the gem to our gem’s user_directory_client.gemspec
gem.add_dependency "sham_rack"
Now we can
require 'sinatra'
require 'sham_rack'
module UserDirectory
class FakeService < Sinatra::Base
###################
# ShamRack methods
def self.activate!
ShamRack.mount(self, "user-directory.example.com", 80)
end
def self.deactivate!
ShamRack.unmount_all
end
###################
# Sinatra methods
configure do
set :raise_errors, true
set :show_exceptions, false
end
USER_JSON = {:name=>'Jenny', :phone=>'867-5309'}.to_json
get '/users.json' do
content_type 'text/json'
[USER_JSON] # :hardcoded list of 1 user
end
# :create new user
post '/users.json' do
content_type 'text/json'
USER_JSON # pretend to create and return hardcoded user
end
end
end
Its very simple and will always return the same hardcoded user but that might be enough. We turn the fake service on and off with calls to UserDirectory::FakeService.activate! and UserDirectory::FakeService.deactivate!. Let’s take a look.
UserDirectory::FakeService.activate!
# => PeopleServices::FakePeopleService
UserDirectory::User.all
# => [#<UserDirectory::User:0x12c52f0a8 @name="jenny", @phone="867-5309">]
UserDirectory::User.create(:name => 'alex', :phone => '555-1212')
# => #<UserDirectory::User:0x12b8731e8 @name="jenny", @phone="867-5309">
UserDirectory::User.create(:name => 'pat')
# => #<UserDirectory::User:0x12b86cc58 @name="jenny", @phone="867-5309">
UserDirectory::User.all
# => [#<UserDirectory::User:0x12b865cf0 @name="jenny", @phone="867-5309">]
This is interesting. Its fast and eliminates the dependency, but its all hardcoded! When we created 2 users we still got the same “Jenny” user every time. The good news is the fake service is just a class we wrote so we can make is as complex as we need. Perhaps what we have here is enough for you and you’re all done but we’ll assume you want something a bit more realistic.
We’re going to create a quick array to simulate persisting our users.
require 'sinatra'
require 'sham_rack'
module UserDirectory
class FakeService < Sinatra::Base
# ShamRack methods ... remain unchanged
# Sinatra methods ... changed to use our new "business logic"
get '/users.json' do
self.class.users.to_json
end
post '/users.json' do
create_user(params)
end
###################
# Some "business logic"
# the worlds simplest db :)
def self.users
@users ||= []
end
def create_user attributes
attributes['id'] = rand(10000)
self.class.users << attributes.dup
attributes.to_json
end
end
end
One last time we’re going to try it out.
UserDirectory::FakeService.activate!
# => PeopleServices::FakePeopleService
# We start off empty
UserDirectory::User.all
# => []
# Create some users - the attributes correctly change
UserDirectory::User.create(:name => 'alex', :phone => '555-1212')
# => #<UserDirectory::User:0x12b85f300 @name="alex", @phone="555-1212">
UserDirectory::User.create(:name => 'pat')
# => #<UserDirectory::User:0x12b857880 @name="pat">
# Now we have our 2 users
UserDirectory::User.all
# => [#<UserDirectory::User:0x12b851318 @name="alex", @phone="555-1212">, #<UserDirectory::User:0x12b84adb0 @name="pat">]
This is now looking almost like a real service and will be very useful as we do our development. One last enhancement is that it’ll be nice to test what happens when the service has errors.
require 'sinatra'
require 'sham_rack'
module UserDirectory
class FakeService < Sinatra::Base
# Everything else unchanged...
def self.fail_next_request!
@fail_next_request = true
end
def self.should_fail_request?
should_fail = @fail_next_request
@fail_next_request = false
should_fail
end
# Sinatra before filter
before do
halt 500, 'We were told to fail!' if self.class.should_fail_request?
end
end
end
One last time we’ll try it out.
UserDirectory::FakeService.activate!
# => true
UserDirectory::FakeService.fail_next_request!
# => true
UserDirectory::User.create :name => 'Alex'
RuntimeError: 500: We were told to fail!
from /Users/alex/user_directory_client/lib/user_directory/user.rb:25:in `create'
from (irb):56
Now go off and create a client for any service you create and be sure to include a fake service!
Software as a service (SaaS) is a great thing. I love that other people are providing services and I don’t have to implement them myself. I can use Airbrake for error notifications and even Twitter for communication. It frees me to focus on what’s unique about my app. Its great that they all work with open standards like HTTP, JSON and XML. But what I like even more is not having to think about HTTP, JSON or XML! When writing a Ruby application I want to think about Ruby. The services I really like provide a gem that hides the transport api details and lets me write plain ruby.
Airbrake.notify(ex)Twitter.user_timeline("sferik")If you are creating a service yourself or even using someone else’s service it’s not too hard to create your own client gem. Let’s look at an example how we can do that.
Imagine you’re building a user directory that lets you list users, create users, update users, show users, delete users, you know, the standard RESTFUL actions. For instance we could create a user and list all users like this
[~]$ curl -F 'user[name]'='Mickey Mouse' http://user-directory.example.com/users.json
{"user":{"name":"Mickey Mouse","id":1001}}
[~]$ curl http://user-directory.example.com/users.json
[{"user":{"name":"Mickey Mouse","id":1001}}]
This is great to use from CURL but writing the code to talk http form fields and parse json will get pretty tiring. I’d much rather have a UserDirectory::User object that behaved similarly to an ActiveRecord model. When we’re done we want to be able to have it work this
user = UserDirectory::User.create(:name => 'Jenny', :phone => '867-5309')
# => #<UserDirectory::User:0x10239b0b8 @name="Jenny", @phone="867-5309", @id=1001>
user.name
# => 'Jenny'
user.id
# => 1001
UserDirectory::User.all
# => [ #<UserDirectory::User:0x102375638 @name="Jenny", @phone="867-5309", @id=1001> ]
We’ll want to wrap this client into a gem so it can be reused by many applications. I prefer to use bundler and its bundle gem command to start my gem. I’ll assume you know how to do that - check out this railscast if you’ve never done it before.
We’re going to get started by building a model class to represent the user without actually connecting it to our service yet.
module UserDirectory
class User
include ActiveModel::Validations
validates_presence_of :name
attr_accessor :name, :phone
def initialize(attributes={})
attributes.each do |name, value|
send("#{name}=", value)
end
end
end
end
I hope you didn’t think all model classes had to subclass ActiveRecord::Base! For me a model represents a concept in the application domain and does not have to map to a database table!
The magic in here is that we’re mixing in the ActiveModel::Validations module. This lets us add the same validations we would to a “regular” ActiveRecord model - in this case validates_presence_of :name. When Rails 3.0 came along much of the functionality of ActiveRecord was extracted into ActiveModel which lets you make any ruby object feel like ActiveRecord and as with most other topics Ryan Bates has put together a great railscast.
When we try it out it behaves as we expect.
# A valid user
user = UserDirectory::User.new(:name => 'alex')
# => #<UserDirectory::User:0x12b79fff0 @name="alex">
user.valid?
# => true
# an invalid user
user = UserDirectory::User.new(:phone => '555-1212')
# => #<UserDirectory::User:0x12b78ecf0 @phone="555-1212">
user.valid?
# => false
user.errors
# => #<ActiveModel::Errors:0x12b788f80 @base=#<UserDirectory::User:0x12b78ecf0
# @errors=#<ActiveModel::Errors:0x12b788f80 ...>, @validation_context=nil, @phone="555-1212">,
# @messages=#<OrderedHash {:name=>["can't be blank"]}>>
The next step is to make our model interact with the service using HTTP and JSON. I’m going to be using the HTTParty gem. It is much easier to use than net/http and automatically parses json or xml into a ruby hash for us.
First, we’ll add a create method that tells the service to create a new user as long as we pass our validations and then returns a User instance.
module UserDirectory
class User
# all the existing code and...
def attributes
{ :name => name, :phone => phone }
end
include HTTParty
base_uri 'http://user-directory.example.com'
def self.create attributes
user = new(attributes)
return user unless user.valid?
response = post('/users.json', :body => user.attributes)
raise "#{response.code}: Better error handling please" unless response.success?
self.new(response.parsed_response)
end
end
end
We can do the same for an all method that returns an array of all users stored in the service.
module UserDirectory
class User
# all the existing code and...
def self.all
response = get('/users.json')
raise "#{response.code}: Better error handling please" unless response.success?
response.parsed_response.map do |user_attributes|
self.new user_attributes
end
end
end
end
Let’s try it out.
# No users yet
UserDirectory::User.all
# => []
# Create a user
UserDirectory::User.create(:name => 'alex', :phone => '555-1212')
# => #<UserDirectory::User:0x12c52f0a8 @name="alex", @phone="555-1212">
# Now ask the service again
UserDirectory::User.all
# => [#<UserDirectory::User:0x12b8890d8 @name="alex", @phone="555-1212">]
This is great! We have a class that’s easy to use, behaves like a normal model but actually talks JSON and HTTP to a remote service. We could continue along the same lines to implement the other methods we need like find & destroy but I’m not going to bore you with that here. Instead I’ll switch gears and talk about building a fake service to eliminate the need to have the actual service running during development and testing.
There are a few reasons we want to build a fake service.
How do we create a fake service? Luckily there’s a gem for that! The ShamRack gem intercepts http calls before they leave our app and redirects them to a local Rack App we’ll create. We’ll create a simple sinatra app that implements the UserDirectory Service API and embed it in our gem.
First things first, add the gem to our gem’s user_directory_client.gemspec
gem.add_dependency "sham_rack"
Now we can
require 'sinatra'
require 'sham_rack'
module UserDirectory
class FakeService < Sinatra::Base
###################
# ShamRack methods
def self.activate!
ShamRack.mount(self, "user-directory.example.com", 80)
end
def self.deactivate!
ShamRack.unmount_all
end
###################
# Sinatra methods
configure do
set :raise_errors, true
set :show_exceptions, false
end
USER_JSON = {:name=>'Jenny', :phone=>'867-5309'}.to_json
get '/users.json' do
content_type 'text/json'
[USER_JSON] # :hardcoded list of 1 user
end
# :create new user
post '/users.json' do
content_type 'text/json'
USER_JSON # pretend to create and return hardcoded user
end
end
end
Its very simple and will always return the same hardcoded user but that might be enough. We turn the fake service on and off with calls to UserDirectory::FakeService.activate! and UserDirectory::FakeService.deactivate!. Let’s take a look.
UserDirectory::FakeService.activate!
# => PeopleServices::FakePeopleService
UserDirectory::User.all
# => [#<UserDirectory::User:0x12c52f0a8 @name="jenny", @phone="867-5309">]
UserDirectory::User.create(:name => 'alex', :phone => '555-1212')
# => #<UserDirectory::User:0x12b8731e8 @name="jenny", @phone="867-5309">
UserDirectory::User.create(:name => 'pat')
# => #<UserDirectory::User:0x12b86cc58 @name="jenny", @phone="867-5309">
UserDirectory::User.all
# => [#<UserDirectory::User:0x12b865cf0 @name="jenny", @phone="867-5309">]
This is interesting. Its fast and eliminates the dependency, but its all hardcoded! When we created 2 users we still got the same “Jenny” user every time. The good news is the fake service is just a class we wrote so we can make is as complex as we need. Perhaps what we have here is enough for you and you’re all done but we’ll assume you want something a bit more realistic.
We’re going to create a quick array to simulate persisting our users.
require 'sinatra'
require 'sham_rack'
module UserDirectory
class FakeService < Sinatra::Base
# ShamRack methods ... remain unchanged
# Sinatra methods ... changed to use our new "business logic"
get '/users.json' do
self.class.users.to_json
end
post '/users.json' do
create_user(params)
end
###################
# Some "business logic"
# the worlds simplest db :)
def self.users
@users ||= []
end
def create_user attributes
attributes['id'] = rand(10000)
self.class.users << attributes.dup
attributes.to_json
end
end
end
One last time we’re going to try it out.
UserDirectory::FakeService.activate!
# => PeopleServices::FakePeopleService
# We start off empty
UserDirectory::User.all
# => []
# Create some users - the attributes correctly change
UserDirectory::User.create(:name => 'alex', :phone => '555-1212')
# => #<UserDirectory::User:0x12b85f300 @name="alex", @phone="555-1212">
UserDirectory::User.create(:name => 'pat')
# => #<UserDirectory::User:0x12b857880 @name="pat">
# Now we have our 2 users
UserDirectory::User.all
# => [#<UserDirectory::User:0x12b851318 @name="alex", @phone="555-1212">, #<UserDirectory::User:0x12b84adb0 @name="pat">]
This is now looking almost like a real service and will be very useful as we do our development. One last enhancement is that it’ll be nice to test what happens when the service has errors.
require 'sinatra'
require 'sham_rack'
module UserDirectory
class FakeService < Sinatra::Base
# Everything else unchanged...
def self.fail_next_request!
@fail_next_request = true
end
def self.should_fail_request?
should_fail = @fail_next_request
@fail_next_request = false
should_fail
end
# Sinatra before filter
before do
halt 500, 'We were told to fail!' if self.class.should_fail_request?
end
end
end
One last time we’ll try it out.
UserDirectory::FakeService.activate!
# => true
UserDirectory::FakeService.fail_next_request!
# => true
UserDirectory::User.create :name => 'Alex'
RuntimeError: 500: We were told to fail!
from /Users/alex/user_directory_client/lib/user_directory/user.rb:25:in `create'
from (irb):56
Now go off and create a client for any service you create and be sure to include a fake service!
I read this information about Indian coins in one Consumer magazine.
Indian coins are mainly produced in four cities:- Delhi,Mumbai, Hyderabad and Kolkata. The production in city puts an identification mark under the year of issue. Coins produced in:
1. Delhi - have a dot
2. Mumbai - have a diamond
3. Hyderabad - have a star
4. Kolkata - nothing beneath the year.
http://www.oceanofweb.com/interesting/facts-indian-coins.html
<object height='300' width='400'> <param></param> <param></param> <param></param><embed src='http://www.flickr.com/apps/slideshow/show.swf?v=107931' height='300' width='400'></embed></object>
The Randonneuring Meetup was fun :)
![]() |
Every time you start a new Ruby project, probably one of the first things you do is write a Gemfile and then run bundle install. Bundler has truly made all of our lives much easier… we know it will install the proper version of all the gems we need. But how does it actually work? This week I decided to take a closer look at the Bundler code itself to find out. How does it know which gems to install? How does it guarantee each gem’s dependencies will be satisfied? How do I get just the right “bundle” my app needs?
Bikers from Bangalore who took part in the Paris-Brest-Paris 2011
What: Movie nite – PBP: The incredible journey
Where: BumsOnTheSaddle
What time: meetup at 6:30pm
Signup: on the facebook event page, if you like
The usual BOTS Movie nite fundas – get your friends, everyone is welcome, more the merrier and BYOB of course ;)
It all started with a call from one lone biker, Venkatachalam – “How about conducting some long distance rides in Bangalore ? Maybe give the PBP a shot ?“
And it culminated with 5 bikers from Bangalore having an ride of their life at the phenomenal 1200Km Paris-Brest-Paris ride
There is a lot that happened in between and a bunch of stars which made it all happen – lots n lots of planning and riding, a good dash of exciting stories and some really really hard work. Game changers!
A big shout out to everyone who put in work to make this happen. There are just too many to talk about here.
The 5 folks who rode the PBP this year
We would be meeting up this Saturday at 6:30pm – all the folks who helped conduct the Bangalore Brevets, the 5 riders who rode the 1200Kms and you of course.
We will also be playing the Paris-Brest-Paris: The Incredible Journey to get an idea of how the 2007 ride went and watch snaps taken by the folks at the PBP
Simple.
All you need is some cable ties and some chain links from your chain ;)
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.
We are watching a selection of movies from Pink Bike this Monday
1. Why – Monday’s are boring. We want to spice up your life.
2. BYOB event – so BYOB please.
3. Everyone is welcome. Really.
![]() |
| Part of a gem dependency network graph |
This week I just discovered Bundler’s best kept secret: the bundle viz command will generate a network graph showing the dependencies among all the different gems used by your Ruby app. For example, the image on the left is a portion of the gem dependency graph for a vanilla Rails 3.1 app. Click here to see the entire, uncropped dependency graph. The gems actually called out in your Gemfile are displayed in grey, while other gems included through dependencies only are shown in white. Finally gem groups are shown as rectangles along the top…
BBCh #8 is all about introducing Cyclocross to Bangalore.
Helmet are mandatory. No excuses.
We race for 45mins and at the indication of the completion of the time, we race the last lap.
rubygems.org has made it so easy to publish a gem for the world to use but what do you do when your gem is proprietary and you only want to publish it within your company?
This is something I’ve just been through at my company and thought I’d share the steps I went through. We need to
The first thing you have to decide is what gemserver to use. Rubygems.org has a helpful page called running your own gemserver that basically lists 3 choices in a goldilocks situation.
too small - gem server is a command built into rubygems
This works but you need to log onto the server to install a new gem and it serves all gems on the system not just your proprietary ones
too big - rubygems.org is open source so we could deploy it on our own server
This seems pretty complex to setup and even they tell you to “consider checking out Geminabox”
just right - gem in a box is a simple sinatra app to allow you to host your own in-house gems
This is easy to setup, has a web interface and supports a command line to remotely publish new gems.
geminabox is what I decided to go with.
The readme on github describes the server setup for geminabox and it just worked. The only thing to keep in mind is that you cannot use bundler as then you will only serve the gems in the bundle instead of the gems you publish. I spent some time adding bundler before realizing that was a bad idea and backing it out.
Once geminabox is up and running you can view your gems at your internal url and you’ll see the gem server homepage showing you it has no gems.

The easiest thing is to add a new gem by clicking “Upload Another Gem” and selecting a .gem file from your hard drive (I picked diagnostics-0.0.1.gem in the image below).

Once you click uppload you should see your gem on the page.

At this point we could start using this gem server in our apps but before we talk about that let’s automate the manual process we just went through to add a gem.
I’ve been using bundler to create my gems with the bundle gem command and one of the features that gives you is a set of nice rake tasks. Check out the New Gem with Bundler Railscast to learn how it works.
$ bundle gem my_awesome_gem
create my_awesome_gem/Gemfile
create my_awesome_gem/Rakefile
create my_awesome_gem/.gitignore
create my_awesome_gem/my_awesome_gem.gemspec
create my_awesome_gem/lib/my_awesome_gem.rb
create my_awesome_gem/lib/my_awesome_gem/version.rb
Initializating git repo in /Users/alex/my_awesome_gem
Let’s look at the tasks we’ve got.
$ cd my_awesome_gem
$ rake -T
rake build # Build my_awesome_gem-0.0.1.gem into the pkg directory
rake install # Build and install my_awesome_gem-0.0.1.gem into system gems
rake release # Create tag v0.0.1 and build and push my_awesome_gem-0.0.1.gem to Rubygems
rake build and rake install do their work locally but rake release is what you call when you’re done and ready to release your gem into the wild. This task will push your changes to github, create a git tag, build your gem package and deploy it to http://rubygems.org. We need to do something to change that last part so it deploys to our private gem server instead of rubygems.org.
Let’s spend some time looking into bundler to figure out how rake release works. The magic all happens inside a file lib/bundler/gem_helper.rb
gem push pkg/my_awesome_gem-0.0.1.gem which pushes to http://rubygems.org. We’ve found the behavior we need to change.geminabox adds a custom rubygems command called inabox so you can deploy a gem with the command gem inabox pkg/my-awesome-gem-1.0.gem. Unfortunately bundler does not seem to have a convenient way to change this so we’re going to monkey patch bundler Bundler::GemHelper#rugygem_push method to use the geminabox command instead. (please let me know if you have a better idea)
We’ll add our monkey patch to our Rakefile since its called by a rake command.
# Rakefile in your my_awesome_gem gem
# Monkey patch Bundler gem_helper so we release to our gem server instead of rubygems.org
module Bundler
class GemHelper
def rubygem_push(path)
gem_server_url = 'http://gems.intranet.mycompany.com'
sh("gem inabox '#{path}' --host #{gem_server_url}")
Bundler.ui.confirm "Pushed #{name} #{version} to #{gem_server_url}"
end
end
end
You can see this will call gem inabox ... so we also need to add geminabox to our gem’s bundle. We do this in the .gemspec as a development dependency
# my_awesome_gem.gemspec in your gem
Gem::Specification.new do |s|
.. lots of other stuff ...
s.add_development_dependency "geminabox"
end
Now when we call rake release it will push the gem to our private server instead of the public one. Let’s see:
$ rake release
my_awesome_gem 0.0.1 built to pkg/my_awesome_gem-0.0.1.gem
Tagged v0.0.1
Pushed git commits and tags
Pushed my_awesome_gem 0.0.1 to http://gems.intranet.mycompany.com
Now when we go to the gem server site, we can see our new awesome gem in the list

The gem is there an you can use install it with a command like gem install my_awesome_gem --source http://gems.intranet.mycompany.com
We’ve just seen how we can use the source option to tell rubygems where to look when installing our gem by hand, but in a modern application we all use bundler and a Gemfile to manage our gems so how do we tell bundler to user our private gemserver for our private gems? Its super simple, you just need to add a source to the top of your Gemfile
source "http://gems.intranet.mycompany.com/"
source :rubygems
# regular old gems come from rubygems.org
gem "rails"
gem "rack"
gem "haml"
# my private gem comes from my private gemserver
gem 'diagnostics'
Now when we run bundle it looks in our private gem server as well as the public rubygems.org. Now that that you’ve got my_awesoem_gem you’re ready to add awesomeness to your app.
$ bundle
Fetching source index for http://gems.intranet.mycompany.com/
Fetching source index for http://rubygems.org/
Using rake (0.9.2)
Using activesupport (3.1.0)
Installing my_awesome_gem (0.0.1)
...etc..
rubygems.org has made it so easy to publish a gem for the world to use but what do you do when your gem is proprietary and you only want to publish it within your company?
This is something I’ve just been through at my company and thought I’d share the steps I went through. We need to
The first thing you have to decide is what gemserver to use. Rubygems.org has a helpful page called running your own gemserver that basically lists 3 choices in a goldilocks situation.
too small - gem server is a command built into rubygems
This works but you need to log onto the server to install a new gem and it serves all gems on the system not just your proprietary ones
too big - rubygems.org is open source so we could deploy it on our own server
This seems pretty complex to setup and even they tell you to “consider checking out Geminabox”
just right - gem in a box is a simple sinatra app to allow you to host your own in-house gems
This is easy to setup, has a web interface and supports a command line to remotely publish new gems.
geminabox is what I decided to go with.
The readme on github describes the server setup for geminabox and it just worked. The only thing to keep in mind is that you cannot use bundler as then you will only serve the gems in the bundle instead of the gems you publish. I spent some time adding bundler before realizing that was a bad idea and backing it out.
Once geminabox is up and running you can view your gems at your internal url and you’ll see the gem server homepage showing you it has no gems.

The easiest thing is to add a new gem by clicking “Upload Another Gem” and selecting a .gem file from your hard drive (I picked diagnostics-0.0.1.gem in the image below).

Once you click uppload you should see your gem on the page.

At this point we could start using this gem server in our apps but before we talk about that let’s automate the manual process we just went through to add a gem.
I’ve been using bundler to create my gems with the bundle gem command and one of the features that gives you is a set of nice rake tasks. Check out the New Gem with Bundler Railscast to learn how it works.
$ bundle gem my_awesome_gem
create my_awesome_gem/Gemfile
create my_awesome_gem/Rakefile
create my_awesome_gem/.gitignore
create my_awesome_gem/my_awesome_gem.gemspec
create my_awesome_gem/lib/my_awesome_gem.rb
create my_awesome_gem/lib/my_awesome_gem/version.rb
Initializating git repo in /Users/alex/my_awesome_gem
Let’s look at the tasks we’ve got.
$ cd my_awesome_gem
$ rake -T
rake build # Build my_awesome_gem-0.0.1.gem into the pkg directory
rake install # Build and install my_awesome_gem-0.0.1.gem into system gems
rake release # Create tag v0.0.1 and build and push my_awesome_gem-0.0.1.gem to Rubygems
rake build and rake install do their work locally but rake release is what you call when you’re done and ready to release your gem into the wild. This task will push your changes to github, create a git tag, build your gem package and deploy it to http://rubygems.org. We need to do something to change that last part so it deploys to our private gem server instead of rubygems.org.
Let’s spend some time looking into bundler to figure out how rake release works. The magic all happens inside a file lib/bundler/gem_helper.rb
gem push pkg/my_awesome_gem-0.0.1.gem which pushes to http://rubygems.org. We’ve found the behavior we need to change.geminabox adds a custom rubygems command called inabox so you can deploy a gem with the command gem inabox pkg/my-awesome-gem-1.0.gem. Unfortunately bundler does not seem to have a convenient way to change this so we’re going to monkey patch bundler Bundler::GemHelper#rugygem_push method to use the geminabox command instead. (please let me know if you have a better idea)
We’ll add our monkey patch to our Rakefile since its called by a rake command.
# Rakefile in your my_awesome_gem gem
# Monkey patch Bundler gem_helper so we release to our gem server instead of rubygems.org
module Bundler
class GemHelper
def rubygem_push(path)
gem_server_url = 'http://gems.intranet.mycompany.com'
sh("gem inabox '#{path}' --host #{gem_server_url}")
Bundler.ui.confirm "Pushed #{name} #{version} to #{gem_server_url}"
end
end
end
You can see this will call gem inabox ... so we also need to add geminabox to our gem’s bundle. We do this in the .gemspec as a development dependency
# my_awesome_gem.gemspec in your gem
Gem::Specification.new do |s|
.. lots of other stuff ...
s.add_development_dependency "geminabox"
end
Now when we call rake release it will push the gem to our private server instead of the public one. Let’s see:
$ rake release
my_awesome_gem 0.0.1 built to pkg/my_awesome_gem-0.0.1.gem
Tagged v0.0.1
Pushed git commits and tags
Pushed my_awesome_gem 0.0.1 to http://gems.intranet.mycompany.com
Now when we go to the gem server site, we can see our new awesome gem in the list

The gem is there an you can use install it with a command like gem install my_awesome_gem --source http://gems.intranet.mycompany.com
We’ve just seen how we can use the source option to tell rubygems where to look when installing our gem by hand, but in a modern application we all use bundler and a Gemfile to manage our gems so how do we tell bundler to user our private gemserver for our private gems? Its super simple, you just need to add a source to the top of your Gemfile
source "http://gems.intranet.mycompany.com/"
source :rubygems
# regular old gems come from rubygems.org
gem "rails"
gem "rack"
gem "haml"
# my private gem comes from my private gemserver
gem 'diagnostics'
Now when we run bundle it looks in our private gem server as well as the public rubygems.org. Now that that you’ve got my_awesoem_gem you’re ready to add awesomeness to your app.
$ bundle
Fetching source index for http://gems.intranet.mycompany.com/
Fetching source index for http://rubygems.org/
Using rake (0.9.2)
Using activesupport (3.1.0)
Installing my_awesome_gem (0.0.1)
...etc..
Ever wanted to gift a biker some bicycling related item and not sure what to gift them ?
How about some BOTS Currency ?
My friend Richard is an all-around fabulous person. He lives a glittering life, full of fashion and fundraising and other sparkly things. He also, as it happens, makes a mean corn salad.
When we headed to Abby & Jason's apartment for dinner a few weeks ago (Abby is Richard's sister; Jason is my cousin.), I contributed a peach-blueberry pie, and Richard brought this incredible salad. It was so simple, but so good. He mixed together raw, sweet corn, red onion, feta, avocado and - though he left a bit out of mine, knowing how I feel about it - cilantro.
I couldn't believe how creamy and salty and sweet the whole thing was. It went beautifully with the steak and potatoes Abby and Jason served, and it was just such a perfect dish for the end of summer. You know how it is - we're coming to the end of the bounty of ridiculously delicious summer produce, and you just want as much of it as you can get.
The version I made at home featured basil instead of cilantro (obviously), and mascarpone instead of feta, since that was what I had. I haven't written up a recipe for it yet - though hopefully I'll be able to soon: I have two precious ears of local New York corn waiting in the fridge.
Every Monday Bicycling Movie nite – we intend to watch a biking movie every monday evening. Start around 7:30pm and wrap up in about 45 mins.
We are watching a selection of movies from Pink Bike this Monday
1. Why – Monday’s are boring. We want to spice up your life.
2. BYOB event – so BYOB please.
3. Everyone is welcome. Really.
Sometimes, you just need a really simple salad. Last week was just such a time. I was overwhelmed at work, busy and home, and generally a bit wiped out. Cooking anything with a measure of complexity was simply beyond my means, and so I turned to one of the simplest standbys I know.
Sliced tomatoes (heirloom or otherwise; just make sure they're tasty and not bland), sliced red onion, torn basil, good balsamic vinegar (it should be a bit syrupy and rich and a bit sweet, not runny and tangy) and sea salt.
It satisfies the tummy and the soul.
config.consider_all_requests_local = true default :charset => 'utf-8' default :mime_version => '1.0'
default :parts_order => [ "text/plain", "text/enriched", "text/html" ]
Hi Folks, I have recently written about my Rails Contributions experience here. I see that now days contribution is Rails is increased. People love to contribute in Open Source projects. And the way should be easy not painful. I found that some people are struggling in submitting Pull Requests in Rails on Github. So i thought [...]
If you are facing below issue while installing mysql gem on ubuntu then you need to install 'libmysqlclient-dev' library.
manohar@manohar-Inspiron-1525:~$ gem install mysql
Building native extensions. This could take a while...
ERROR: Error installing mysql:
ERROR: Failed to build gem native extension.
/home/manohar/.rvm/rubies/ruby-1.9.2-p290/bin/ruby extconf.rb
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lmygcc... no
checking for mysql_query() in -lmysqlclient... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers. Check the mkmf.log file for more
details. You may need configuration options.
Provided configuration options:
--with-opt-dir
--without-opt-dir
--with-opt-include
--without-opt-include=${opt-dir}/include
--with-opt-lib
--without-opt-lib=${opt-dir}/lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=/home/manohar/.rvm/rubies/ruby-1.9.2-p290/bin/ruby
--with-mysql-config
--without-mysql-config
--with-mysql-dir
--without-mysql-dir
--with-mysql-include
--without-mysql-include=${mysql-dir}/include
--with-mysql-lib
--without-mysql-lib=${mysql-dir}/lib
--with-mysqlclientlib
--without-mysqlclientlib
--with-mlib
--without-mlib
--with-mysqlclientlib
--without-mysqlclientlib
--with-zlib
--without-zlib
--with-mysqlclientlib
--without-mysqlclientlib
--with-socketlib
--without-socketlib
--with-mysqlclientlib
--without-mysqlclientlib
--with-nsllib
--without-nsllib
--with-mysqlclientlib
--without-mysqlclientlib
--with-mygcclib
--without-mygcclib
--with-mysqlclientlib
--without-mysqlclientlib
Use below command to resolve above issue-
manohar@manohar-Inspiron-1525:~$ sudo apt-get install libmysqlclient-dev
![]() |
| “Kaminari” means thunder in Japanese |
Kaminari is a popular new gem that provides pagination behavior – to learn how to use it see the Railscast Pagination with Kaminari, or just refer to the Github readme page. For me Kaminari is a good example of “Rails magic…” somehow by just adding the gem to my Rails application all of my models get the Kaminari page method. I don’t have even have to type a single line of code in my model… it’s just automatically added for me. Then when I call page, it immediately works: returning just the records for a given page, even working in conjunction with other scopes I might have…
My colleague Zainab and I will be presenting in the Pecha Kucha sessions at Agile Day 2011 Conference on 27th September, 2011. Hear our thoughts and experiences with Agile as we share them in a conversation with Jochen Krebs - Founder of Agile NYC in the latest Agile NYC podcast.
Also check out the very impressive lineup of speakers for the conference (Amy Goodman and Linda Rising are key-note speakers). There are limited seats available, so register soon if you are interested in attending the conference.
All you need is an egg and some imagination:
Julia child is so cute in this video. Got the perfect recipe for binge day..check out 24:02 in the video. Omlette with sauteed mushrooms, topped with cheese sauce, topped with cheese and then melted butter. Yummy.
Dil Tera deewana hai sanam, jaante ho tum, kuch na kahenge hum..
Jalta hai jiya mera bheegi bheegi raaton mein, aaja gori chori chori abto rahan nahin jaye re, uhum hai re hai re hai re…
Bheegi bheegi raaton mein, meethi meethi baaton mein, aisi bursaaton mein, kaisa lagta hai..
The Trek 1.1 was reviewed by Darren Reid. We wrap up the review with our thoughts on certain technical/non-technical aspects of the bike.
Darren Reid is a pro biker from Australia who is currently in India. He is currently sponsored by Rapha clothing (the Prada of bicycling clothing) and embrocation cycling magazine (it`s a great read. Check them out). If you like what you see, you’re welcome to ping Darren and order stuff thru him.
Darren has been racing for over 20 years and is currently helping us build and improve the Bangalore Bicycle Championships. Definitely good to have someone so experienced in our formative years!
Here’s Darren has to say about his Trek 1.1
Rating the new Trek 1.1 wasn’t so hard – an excellent all rounder.
A frame designed by Trek Wisconsin, a great looking paint job, a Trek Alpha aluminum frame and fork and the thoughtful eyelets in the front and the rear for racks! The generous wheel clearance also allows for mudguards which add to the versatility of the 1.1, great for the upcoming monsoons and carrying your bag and laptop to the office!
The bike has a solid entry level Shimano groupset (Shimano 2300), Bontrager components and an FSA crank. The Trek 1.1 is not a light weight racing machine, but the 23C tires, the compact design and the racing short wheel base definitely gives you a feeling of race worthiness. It is really a bike you can use for everything – you could commute to work all week with mud guards and racks, ride it home on a friday, knock down a couple of beers and convert it into a weekend racing machine. All set to ride and train hard.
A Trek road bike under 30k. Smart buy indeed!
I have had the Trek 1.1 for a couple of days – its not as light as my other racing machines, but it did handle very very well. The ride up and down our local climb, Nandi Hills, was responsive and the bike handled very well. The compact crank allows for comfortable gear ratios to climb Nandi, especially the 34 front chainring up Nandi hill which had me spinning like Lance :-)
The Shimano 2300 never missed a gear.
I also found the aluminum frame to soak up a lot of bumps where there where bad road surfaces. I’m sure it would be a good bike for long distance Brevet rides that seem to be popular in Bangalore at the moment.
Sure I could pick things I would like to change on it, but at the end of the day it’s an excellent all rounder and great value for money given that it is a Trek and that it’s priced at under Rs. 30,000.
I would say go for it!!!
The Trek 1.1 gets out of 5
How do we review a bike ?
At BumsOnTheSaddle we typically consider quite a few parameters before recommending a bike (We recommend only those bikes that we would buy or ride ourselves).
BOTS Parameters
Like Darren mentioned, the Trek 1.1 is a very good ride indeed and scores pretty high on most of our criteria for recommending it.
We have been using the 1.1 over the last month or so and putting it thru its paces – flats, climbs, descents, commutes, races and longish brevet rides. The bike is versatile indeed! It does lack the responsiveness and acceleration you would expect out of a really good road bike, but then you cannot expect anything better at a sub Rs 50,000 range of bikes.
The bike does not have any carbon on it – which is good considering that its not built to be a speed machine. This allows the costs to be kept down.
The bike also comes with an aluminium fork. Do read our next writeup on why this could be a boon or a bane.
The Shimano 2300 rode surprisingly well. The shifts were crisp and the bike rode exceedingly well on flats, climbs and descents. The 2300 comes with a 11-25 7 speed cassette. The front crank is a 50/32 compact crank. The gear ratios might leave you out of gears and your comfort zone if you are a beginner and hitting steep climbs like Nandi. Other than that the 2300s are great!
Who should buy this bike
If you intend to do some fast racing on this, we would recommend you save a bit more and look at bikes starting in the Rs 50,000 range. It’s worth the ride and you would spend that much or more on this bike with upgrades to get you the experience you are looking for anyways.
We could make a couple of changes to make this bike ride even better – in order of priority
1. Braking – change the brake shoes to something better for a better braking experience and confidence on descents.
2. Tires – swap out the entry level Bontrager tires to racier, lighter, faster tires. Rolling can improve drastically.
3. Wheelset – the entry level wheels could be swapped out for lighter racing wheels for the peppiness you experience on more expensive racing machines. Borrow a friends wheelset and see how good the frame is.
4. Carbon – introduce carbon for better handling, reducing road buzz and comfort. You could swap in a carbon fork and a carbon seatpost.
5. Group set – if you have money left in your kitty you could upgrade to a Tiagra groupset. This would reduce weight, make your ride more efficient and give you much better control over your shifting. The additional sprocket at the rear is definitely a nice to have on your climbs.
all approximate prices susceptible to change
Nick, Louisa and I enjoyed a lovely breakfast at The Breslin last Friday. The coffee was stupendous, the baked eggs with tomato and chorizo simply glorious, and the service, frankly, lacking. At a restaurant of The Breslin's quality, I shouldn't have to wait ten minutes for sugar for my coffee.
But, man, what good coffee it is. Love you, Stumptown.
Every Monday Bicycling Movie nite – we intend to watch a biking movie every monday evening. Start around 7:30pm and wrap up in about 45 mins.
Starting this Monday – 5th September
Time – 7:30pm
Where – BumsOnTheSaddle
We are watching the Season 3 of the Atherton Project this Monday
1. Why – Monday’s are boring. We want to spice up your life.
2. BYOB event – so BYOB please.
3. Everyone is welcome. Really.
Google (re)announced offline feature on Google docs recently. For those who noticed, would also remember that Google Gears was decommissioned nearly an year ago, hence this new HTML 5 version took too long to get to beta status. Is the new offline version worth the wait?
I guess not..here are some important notes about new offline capability (source: Google Docs help)
Fancy and Pretty! A little on the expensive side for what you get though has a few good dishes to try for sure. With three locations around the city Fig and Olive manages to have presence in good parts of the city. The Mediterranean Chicken Samosas are addictive: Chicken, cilantro, Greek yogurt, bell pepper scallion [...]![]()
A bustling place for brunch in the meat packing district of NYC: Pastis Great brunch menu. Make reservations before going – the wait isn’t something you would want to do. If you like other sister restaurants like Balthazaar Resturant, Pravda, Balthazaar bakery, Lucky Strike you will like this one too. Try the Eggs à la [...]![]()
Ten years ago today, I moved to New York City. My first apartment was on a slightly desolate block of the Upper West Side. Today, there's a Whole Foods a block away, and four high rises have gone up within a two-block radius. Times, you could say, have changed.
I've spent my entire adult life here in Manhattan, and I wouldn't trade the experience for the world. My first few weeks were, obviously, colored by the September 11th attacks. I didn't even have my cable hooked up yet and wasn't due to start work for another week, so I spent the day curled up in my hallway listening to the radio. When I left to walk 20 blocks downtown to Caroline's apartment for company, cable and dinner, I passed Brooke Shields on the street.
That's New York, you know? The gritty reality crossed with the glamour of art and, in this case, celebrity - writ large.
My first forays into grown-up cooking were, to say the least, less than exciting. There were many grilled peanut butter and jelly sandwiches (a trick I learned from my slightly older and much wiser roommate), a lot of bottled marinara sauce, and tons of macaroni and cheese. But always a green salad. I've always been addicted to vegetables.
I spent my money at the bars and skimped on my food budget. A fancy night out was dinner at Big Nick's, an all-night pizza and burger joint on Broadway. I came home most nights by way of the local pizza place, slice in hand. I'd leave it in the oven to keep warm, hop in the shower to get rid of the bar smell (those were the days before the smoking ban, when I'd have to hang my coat on the fire escape overnight to air out the cigarette fumes), then eat the cheesy, greasy goodness while watching a movie on my hand-me-down sofa.
Today, I drink booze with flavor (bourbon or gin, not vodka), the dinners are nicer and the nights (mostly) earlier. The produce is fancier and more local, and the apartment a bit more pulled together. But the joy I feel every time I see the New York skyline, the rush I get every morning when I walk out the door, the satisfaction I take in having made it in this most insane and exciting and glorious of cities - that hasn't changed one little bit.
Thank you, New York, for raising me so well. I love you. Which is a good thing, because we seem to be stuck with one another.