Friday, January 20, 2012

Rails 3.2 on Heroku asset:precompile issue

I just upgraded www.checkthesock.com to Rails 3.2 and found that the asset precompile step of the release was not working properly.

Here is the output I was getting:

-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       rake aborted!
       could not connect to server: Connection refused
       Is the server running on host "127.0.0.1" and accepting
       TCP/IP connections on port 5432?
       
       Tasks: TOP => environment
       (See full trace by running task with --trace)
       Precompiling assets failed, enabling runtime asset compilation
       Injecting rails31_enable_runtime_asset_compilation

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'

config.assets.initialize_on_precompile = false

Additional Resources

Monday, November 21, 2011

rescue_from temporary fix for rails 3.0 and 3.1

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.

First set up a simple errors controller:
class ErrorsController < ApplicationController
  def missing_page
   render :status => :not_found
  end
end

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.
In the application controller add the following lines:
rescue_from ActiveRecord::RecordNotFound, :with => :missing_page
rescue_from ActionController::UnknownAction, :with => :missing_page
rescue_from ActionController::RoutingError, :with => :missing_page
The first two lines work as expected, the line with ActionController::RoutingError does not work correctly though, it will start working once the bug is fixed.

The temporary fix for routing errors not being handled properly is to add the following line as the last route in the route file.
match '*path', :to => 'errors#missing_page'

Once the bug is fixed all you need to do to clean this up is remove the line that was placed at the end of the route file.

Thursday, September 8, 2011

Rails Code QA Update

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


Installation
If 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.


Resources

Monday, March 28, 2011

Sitemap testing with doublecheck

I hate releasing a new version of a site and finding out a few days later that I broke some of the pages. So I wrote the Doublecheck gem to help with post release testing.

Doublecheck

Doublecheck pulls a sitemap file and checks each URL listed, outputing a list of URL's for each HTTP status code that is encountered.

Installation

$ gem install doublecheck

Usage

$ doublecheck http://example.com/sitemap.xml

Notes

Get the code: github.com/nathanhumbert/doublecheck

Doublecheck is pretty simple at this point, it does one request at a time, so large sites may take a substantial amount of time to process.

Google's webmaster tools will eventually let you know if one of your pages has a problem, but it isn't a particularly fast way to find issues on your site.

Tuesday, February 15, 2011

Using Sinatra with Bundler to deploy on Heroku

I decided to try using sinatra for a small project I started the other day. I normally work in rails and host my personal projects on heroku. Since rails 3 came out I have also gotten hooked on bundler. I could not find any single source that documented how to use all of these together nicely. Here is how I got it to work.

Gemfile

The gemfile is pretty basic, set a source for gems and include the sinatra gem.
source :rubygems
gem 'sinatra'

config.ru

This is the rackup config file which sets the app up to run in rack.
require 'rubygems'
require 'bundler'

Bundler.require

require './myapp'

run MyApp

myapp.rb

This is the sinatra file. Note that I defined a class (MyApp). This is very important because our config.ru needs the class as a handle for the 'run MyApp' call. An alternative would be to use "run Sinatra::Application" in your config.ru file.
class MyApp < Sinatra::Base
  get '/' do
    'Hello world!'
  end
end

Running locally

First make sure rack is installed, then run the following commands in the root folder and the app should be up and running locally.
bundle install
rackup

Deploying to Heroku

Just run the following commands in the root folder and the app should be up and running on Heroku.
git init
git add .
git commit -m 'Initial version of MyApp'
heroku create
git push heroku master

Additional resources

Sunday, January 23, 2011

Easy data caching in Rails 3

Three common forms of caching

There are 3 types of caching that are very commonly talked about in the rails community; page caching, action caching, and fragment caching. All of these are well documented and are great ways to cache varying amounts of content for your pages.

Is that all the caching I need?

Caching at the view level is great but it isn't necessarily the best fit for every situation. In some cases it may be easier to cache data at a lower level. Perhaps you want to cache the results of an external data request for a given period of time. None of the view caching methods would be a really great fit.

Lower level data caching

Rails 3 actually has a great method for caching data at a lower level than the view. It even uses the same caching store as action and fragment caching. ActiveSupport::Cache::Store allows you to store any serializable Ruby object. Rails even provides an already initialized cache store via Rails.cache.

Example usage and code

I used this on www.checkthesock.com to cache METAR queries. I was using current_metar a gem I built that pulls metar data from ADDS. I made a model called CachedMetar to return cached results to the rest of my application.


Code walk through

This model basically returns the result of the block argument to Rails.cache.fetch the first time it is called. Any time it is called within the next 5 minutes it returns the value that was cached the first time. Everywhere I had previously been calling CurrentMetar::Metar.get_metar("ICAO code") I switched to call CachedMetar.metar("ICAO code") and that was all it took.

Testing

Testing is actually surprisingly easy. I used shoulda and mocha and here is what I ended up with.


Reference

Friday, January 21, 2011

SEO friendly maps with jQuery

In my free time I am working on a social networking site for RC pilots. I have information pages for various RC airfields and I was looking for a good way to display a listing of the fields. Putting markers on an embedded google map is a great way to display this type of data to users. The method I have seen recommended for this is to make separate list and map views. I don't really think that is a great user experience though.

The main reason making two pages is suggested is that maps require many lines of code and JavaScript functions that will dilute your content. The solution I arrived at was to use as little javascript as possible to generate my map. I ended up accomplishing this by using javascript to parse the content of the page to generate the markers.

To be able to easily parse out the data I wanted to display on the map I ended up making my own microformat. I put a class of field on the div that contained each field I was showing on the page. In that div I put the content that I wanted to display in the information popup for each marker. Then in that div I put two spans that contained the latitude and longitude and gave them each a class. The results ended up looking like this:


Then I wrote some javascript to parse this microformat and generate markers for my map. I used jQuery selectors to select each field in the html. For each field the latitude, longitude, and html contents are selected. Then the add_marker method is called to setup the marker with that data. After the marker is created I hide the field div.


Users with javascript will see a map with a bunch of markers that have an information bubble when clicked on. Users that do not have javascript enabled will see a list of field information. The textual content is the same for both users, the users with javascript just get an improved experience.

Go to www.checkthesock.com/fields to see the end result.