We ran into an issue last week where our XML APIs were returning HTML under certain error conditions, rather than the expected XML. Our solution was to add the following code to the ApplicationController:

  rescue_from Exception do |exception|
    respond_to do |format|
      format.xml  { render :xml => 
           "<error>Internal Server Error #{exception.message}</error>", 
           :status => 500 }
      format.html { render :html => {:file => 'public/500.html'}, :status => 500 }
      format.json { render :json => 
            {:error => "Internal Server Error #{exception.message}"}.to_json, 
             :status => 500 }
    end
  end

We might have also declared a rescue_action, and I’m not sure of the benefits of one over the other, except that perhaps we needed to implement a general form of rescue_from since we had another more specific form already declared.

It seemed to me that this should be the default behavior in rails, so I decided to dig into it a little more and see what I could discover. I started by making a little test app to reproduce the exception. The particular case from last week was a database limit that wasn’t being caught in the app with a length validation. When I tried to re-create the error in MySql, I noticed that no exception is thrown since MySql will just truncate the data (although perhaps that is only because I am not running MySql in strict mode). In PostgreSQL, the database layer will throw an exception.

Test app setup:

rails -d postgresql test_postgresql
cd test_postgresql/
script/generate scaffold person first:string last:string present:boolean

Edit the migration to create a database limit:

class CreatePeople < ActiveRecord::Migration
  def self.up
    create_table :people do |t|
      t.string :first, :limit => 40
      t.string :last, :limit => 40
      t.boolean :present

      t.timestamps
    end
  end

  def self.down
    drop_table :people
  end
end

Create the postgres user. Note double-quotes around user, single quotes around password. It has to be that way. Go figure.

$ sudo su postgres -c psql
postgres=# create user "test_postgresql" with superuser password 'password';
CREATE ROLE
postgres=# q

Finally create the database, run migration, and start the server:

 
rake db:create:all
rake db:migrate
./script/server

If you point your browser at http://localhost:3000/people and try to create a person with more that 40 characters in the first name, you will see the following error:

ActiveRecord::StatementInvalid in PeopleController#create
PGError: ERROR:  value too long for type character varying(40)

That is all well and good; however, if you do the same in XML, you will get the same error in HTML.

$ curl -X POST -d "<person><first>This is a first name that is too long for the database limit</first></person>" -H "Content-Type: application/xml" http://localhost:3000/people.xml
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Action Controller: Exception caught</title>
  <style>
    body { background-color: #fff; color: #333; }

    body, p, ol, ul, td {
      font-family: verdana, arial, helvetica, sans-serif;
      font-size:   13px;
      line-height: 18px;
    }

That seems like a bug to me. Perhaps this should be a lighthouse ticket rather than a blog post.. still not confident in identifying bugs in Rails, so I figured I’d post here first.

In my recent explorations of how to teach test-driven development (TDD), I have found a number of people writing about using testing for learning.  First I read how Ross Niemi explored the assert method by testing it. He talked about feeling that he would like to prove that he understood the syntax. Then I read how Mike Clark developed his own test suite to teach himself Ruby. He talks about how he “used the language as a tool to explore itself. In the same way that a test is better than a specification, the language is better than a description of the language. The test is definitive.”

Also, as a response to my last post about test-driven teaching, Seth Walker told me about Ruby Koans, which are a delightful test-driven meditation on Ruby syntax. I find them really fun and have been assigning them as homework in my class.

In my work, I often learn about my design or the implications of my implementation through testing. It is one of the things that is so invigorating about TDD. Discovering testing as a self-paced learning tool was simultaneously surprising and obvious.