Category Archives: ruby on rails

Tales from the Port: Day 1 — Dry Dock

Welcome to my one week blog series, Tales from the Port, chronicling my rewriting of Project Quincy from Ruby on Rails to Django. This series may be a little rough around the edges — I’ll be writing it every night after I accomplish my goals for that day. But I wanted to give people a window into the life of (at least one) Digital Humanities developer. To see what it’s like to imperfectly translate your research and theories into lines of code and then watch your project come ‘alive.’

Of course, Digital Humanities is not about writing code or knowing how to program. DH is a community of people searching for a new way of working and researching, and we find inspiration in many disciplines. But, this is going to be one of the more intense work weeks of my life to date, so I’m hoping you’ll keep me company.

First, some background:

Project Quincy is an open source software package I wrote a few years back to trace historical networks through time and space. It is an integral part of my dissertation and currently runs The Early American Foreign Service Database, which went live almost two years ago on October 18, 2010. Project Quincy got its start at the University of Virginia’s Scholars’ Lab, where I was a graduate student fellow in 2008-2009. I was very pleased with the system when I first designed it, but technology doesn’t stop when your fellowship ends. Faced with an aging code base and an interface that could no longer accomodate the visual arguments which are becoming more and more central to my dissertation, it was time to upgrade. I could have taken Project Quincy from Rails 2.3.8 to 3.0 and tweaked the stylesheet along the way, but I am no longer at the University of Virginia. Last summer I was hired by the Brown University Library as their first Digital Humanities Librarian. My new colleagues program (mostly) in Django, and I’ve already met one or two professors here who could probably use the system for their own research. It was time to learn some new skills.

I have thoroughly enjoyed learning Python and Django, so much so that I will probably write more on them once this week is over. Since finishing up the tutorials, I have spent the last two weeks planning the port. As the week unfolds I’ll discuss how the system is changing and my reasons for making those changes. Although both Django and Rails exist to connect databases to websites with minimal headaches for the programmer, they have different affordances and make very different assumptions about what constitutes beautiful code.

So what have I done today?

Today I created the new Django project which I will be extending into ProjectQuincy. I had hoped to have the entire data model rewritten by now, but no plan survives contact with a new development environment . . . Apparently when I got my new MacBook Pro my MySQL installation did not survive the transfer. It took a few hours of research, then reinstalling MacPorts, before I could really get underway. I will have more to say tomorrow on my changes to the data structure.

Planning this port has been a bittersweet experience. I’ve had a great deal of fun learning a new language and framework. My colleagues at Brown, particularly Birkin Diana and Joseph Rhoads, have been extremely helpful: suggesting good training materials, answering questions, and teaching me the ever crucial “best practices.” Thanks to their help, I am looking forward to having a cleaner, more robust system. But, my fellowship year at Scholars’ Lab is a cherished memory, and so many people there helped and taught me as I figured out how to make The Early American Foreign Service Database a reality. As I worked on the project my friends pitched in, putting their own stamp on the code base. This new, fresh start won’t have code from Bess Sadler, Matt Mitchell, Joe Gilbert, or Wayne Graham. For a little while it will just be my code, and that feels a little lonely. But it won’t last. Soon I’ll be showing the system to my colleagues at Brown, and I can’t wait to see Project Quincy afresh through their eyes.

Partial Dates in Rails with Active Scaffold

As a historian I am constantly frustrated (but bemused) by how computers record time. They are so idealistically precise and hopelessly presentist in their default settings that creating intellectually honest digital history becomes impossible without some serious modifications.

In designing Project Quincy, my open-source software package for tracing historical networks through time and space, I quickly realized that how I handled dates would make or break my ability to design the kinds of interfaces and visualizations I needed to perform my analysis.

As a database designer, however, I balk at entering improperly formatted data into the database (I am firm in my belief that this will always come back to bite you in the end). So while MySQL lets me enter an unknown birth date as 1761-00-00, because it doesn’t require proper date formatting unless running in “NO_ZERO_DATE mode”, if I ever migrated the data to another database (say Postgres) I would be up to my eyebrows in errors. But I also don’t want to mislead my users into thinking that half the individuals in my database were born on January 1st.

So here are my solutions, drawn from the code of Project Quincy, which powers The Early American Foreign Service Database.

A relatively easy way to format partial dates in your frontend interface is to add 3 boolean flags to each date: year_known, month_known, and date_known. Then add the following method into your application helper (link to code here) to determine how you display each type of partial date.

For entering partial dates Project Quincy makes extensive use of ActiveScaffold, a Rails plugin that auto-generates an administrative backend. The nice thing about ActiveScaffold is that it is fully customizable. The problem with ActiveScaffold is that the defaults stink, so you basically end up customizing everything.

By default, ActiveScaffold treats date entry as a unified field, so you have to break up the javascript that knits day, month, and year together. You also have to change the default from today’s date to blank. If you enter only part of a date, it sets the other components to the lowest value possible.

Matt Mitchell, former Head of R&D for the University of Virginia Scholars’ Lab came up with the following elegant solution to my problem:

Create a partial view in /app/views/activescaffold/_common_date_select.html.erb and populate it with the following code.

And activate that partial with a helper method in your application_helper (link here).

And you should be good to go.

**************************************

If the pastie links go down, you can find the partial view and helper methods on Project Quincy at Github.

Troubleshooting Rails Migrations

I’m not sure why this worked, but if it can help anyone else then here it goes . . .

My rails app decided to throw a hissy fit at me by refusing to let me run rake db:migrate because (as it claimed)

rake aborted!
An error has occurred, all later migrations canceled:

Mysql::Error: Table ‘states’ already exists: CREATE TABLE `states` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `name` varchar(255), `continent_id` int(11) NOT NULL, `notes` text, `created_at` datetime, `updated_at` datetime, FOREIGN KEY (continent_id) REFERENCES continents (id)) ENGINE=InnoDB

This was deeply weird because that migration was the 3rd of about 30 migrations in my application. Rails had happily skipped over it in the many months since I had first run it to create the states table, moving directly to the new migrations and running them. Something was wrong, but I had no idea what. After many hours of frustration I stumbled across a viable (albeit hacky) solution to my problem.

Looking at the following thread on Stack Overflow (http://stackoverflow.com/questions/842162/is-rake-dbmigrate-the-correct-command-to-re-sync-schema-rb-with-your-database-sc), I saw that if I commented out the create table in the failing migration and ran rake db:migrate again rails would skip the troubled migration. I meant to do this, but in my haste I only commented out the lines the describing the table, forgetting to comment out the “create_table” and its associated “end” lines of code.

I ran rake db:migrate before I realized this and got the following:

(in /Users/jabauer/pq_eafsd)
== CreateStates: migrating ===================================================
== CreateStates: migrated (0.0000s) ==========================================

I quickly realized my mistake and took out the comments, hoping to put the fields back in the table. When I did so, rake db:migrate ran perfectly. I am pretty new to rails, so I have no idea why this worked or if it is a replicable solution. However, I am offering it to you in the hopes that it will work, save you time, and keep you from having to leave a commented out migration permanently in your app. And, if anyone knows why this worked (or has a better fix), please let me know!