Nathan Humbert's Blog

Thursday, March 15, 2012

I recently checked my current usage on Heroku to find that I had used a much higher than expected number of dyno-hours. The project CheckTheSock.com is a RC aviation website that provides some weather data. The forecast data is pulled every hour via FTP by a rake task that is run with a scheduled job in Heroku. Normally this takes around a minute to run and uses about 13 or 14 dyno-hours in a month. Less than half way through this month I found that it had already burned through over 200 dyno-hours.

After digging into the problem I found that the FTP connection was hanging for some reason. After a little research I came up with a solution that works pretty nicely and for more than just hanging FTP connections.

It turns out that ruby's standard library includes a library named Timeout which provides a way to terminate the execution of a thread. Using this library it is very simple to set a time limit for a block of code in a rake test.

task :task_that_takes_a_long_time_sometimes do
Timeout.timeout(30) do
#The code that takes a long time to run sometimes
end
end

That will raise a Timeout::Error if the code takes longer than 30 seconds to run. The error will cause the rake task to exit, preventing unexpected dyno-hour usage.

Wednesday, February 29, 2012

I recently decided to start doing some A/B testing on www.checkthesock.com. The last time I tried A/B testing I used Google website optimizer, it worked fairly well but I did not like how difficult it was to setup a test. This time I looked around for A/B testing tools for rails. I ended up finding split and so far I have been very happy with the results. The documentation is fairly good but it did take a little fiddling to get it working on Heroku.

First off add the Redis to Go add-on in Heroku, the Nano plan is free and has been sufficient for my needs so far. Install redis on the dev server. I use a mac so that was as simple as "brew install redis" and then I followed the brew instructions for getting redis to start on login.

To install the split gem add the following to the Gemfile

gem 'split', '0.3.3', :require => 'split/dashboard'

To set the development environment up in a way that is compatible to how Redis to Go is configured on Heroku add the following to config/environments/development.rb

ENV['REDISTOGO_URL'] = 'redis://localhost:6379'

Then create an initializer for redis in config/initializers/redis.rb and put the following in that file.

Friday, February 3, 2012

The other day I was working on a change on www.checkthesock.com that involved getting rid of some pages. It is generally a good idea to redirect those URL's to a relevant location so that search engines and people can get to a useful location. Eventually no one uses the old URL anymore and whatever code is redirecting it is just sitting around gathering dust.

I wanted to make sure I eventually cleaned up the code I had doing the redirection. In the past I have tried several different ways of remembering to do this; try to remember, put a note somewhere, or put a reminder in my calendar. None of those have ever ended up working out. None of those methods involve anything that is part of my normal working process.

The solution I came up with was to write a test that checks to see if the code is still around at some future date. I run my tests all the time as part of my normal workflow and I never release code without fixing a broken test. Now at some future point in time the test will break and I will not forget to clean up my unused code. Seems like a potentially useful pattern. In a few months, when my tests start breaking to remind me to clean stuff up, I will discover if it is useful or just really annoying.

Monday, January 23, 2012

I just tracked down and dealt with an issue I was having after upgrading www.checkthesock.com to rails 3.2. After the upgrade assets (css, javascript) were not updating unless I restarted the server process. Took me a while to track down the issue but I finally tracked it down to asset fingerprinting. Asset fingerprinting is off by default in the development environment but I had turned it on to debug an issue a long time ago.

If you are having similar problems make sure that you have the following line in "config/environments/development.rb"

The issue was rails was trying to connect to the database during the precompile process, and heroku is setup not to allow that. I am guessing that this issue is due to a change in the rails initialization setup in rails 3.2.

It turns out that the fix for this is very simple as long as you don't actually need to connect to the database during asset precompiling. All you need to do is add the following line to 'config/application.rb'

Monday, November 21, 2011

In rails 3.0 and 3.1 rescue_from will not successfully rescue a ActionController::RoutingError (Bug Report). Based on comments in the bug report here is the solution I came up with. A way that handles this bug temporarily and once it is fixed all that needs to be cleaned up is a single line in the routes.

The view for missing_page is intended to be shown to visitors as the 404 page, it uses the application layout as set up here but you can set :layout to false or whatever other layout you might wish to use.

Thursday, September 8, 2011

I just released an updated version of Rails Code QA which now supports rails 3.0 and 3.1 as well as ruby 1.8.x and ruby 1.9.x

InstallationIf you are using ruby 1.8.x all you need to do to install rails_code_qa in your rails 3.x app is add the following line to your Gemfile.

gem "rails_code_qa"

If you are using ruby 1.9.x you will also need to add the following to your test/test_helper.rb file

require 'simplecov'
SimpleCov.start 'rails'

Code Coverage
Rails Code QA takes care of picking which code coverage tool to use based on the version of ruby you are using. If you are using ruby 1.8.x code coverage is calculated using rcov and if you are using ruby 1.9.x coverage is calculated using simplecov.

Static Code Analysis
Rails Code QA also runs flog and flay to help you find other issues in your apps code.