My Journey on Rails, Part 1: Tools and Importing Data
We at Wagger Designs have been brewing up a custom web application for some time now. This blog series, in several parts, will follow my research and development process of taking our app from idea to reality. I’ll be sharing techniques and workarounds to issues that arise along the way.
Finding the Tracks
A couple of years ago, I did some preliminary tinkering with Ruby on Rails and took Code School‘s excellent free online course, Rails for Zombies. I was extremely interested in the technology at the time (having been a Lisp geek in college, I’m a little all over the place) but due to my full-time and after-hours commitments at that point, not much traction was made.
More recently (on a related tangent), I started working more with git for SCM during some internal iOS development, and become quite comfortable with it for revision control.
In the first week of May, I decided that Rails would be a good candidate for our new web application, and found myself interested in returning to Code School to take Rails for Zombies 2. Some of the reasons I pegged Rails as a contender:
- It’s a mature, well-structured MVC framework
- Rails features robust ORM with quite a bit of convenience functionality built in
- REST- and SEO-friendly routing with little effort
- Huge, active, knowledgeable community
- Do you really need a reason to [re-]read why’s (poignant) guide to ruby?
There was a slight problem, in that I didn’t really remember anything from the original Rails for Zombies course. After a refresher, I went back over our collective app brainstorming notes and hobbled together a first swipe at the data model.
If you’re looking to follow along but don’t have any experience with Rails, I highly recommend Code School’s classes; however, there are also plenty of other free resources available, including rubyonrails.org’s own Getting Started with Rails guide. There are, in fact, a large number of useful guides there, which you can even download from the main Rails Guides page in .mobi format for Kindle reader apps.
Get This Train Rolling!
After a couple more meetings to sort out a few details and prioritize, we were ready to start writing real code. First things first, we needed a way to import and export batches of spreadsheet data. Our initial data sources will largely be coming from public records and require a decent amount of manual massage to be useful; therefore, it doesn’t make sense to over-architect a solution when CSV via Excel will work just fine in the initial stages.
I go ahead and checkout a new branch for this purpose, and start looking up CSV import/export functionality I can borrow. One of the very first projects I find is database.rake from Synbioz. This project provides the ability import directly into a model table, or allows export of one/all tables in a single shot. I get nervous when I see that it’s over 2 years old, but it’s so close to what I need that I throw caution to the wind and push forward; after all, if it doesn’t pan out, I can just discard my git branch and try again. I clone it per the README into /lib/tasks/database and try to run rake:
cannot load such file -- fastercsv
Oh, right! I forgot to add it to the Gemfile. I do so, and run “bundle install” from the root project folder. Trying again, I discover that my initial fears of the project being stale may have been founded after all:
Please switch to Ruby 1.9's standard CSV library. It's FasterCSV plus support for Ruby 1.9's m17n encoding engine.
That actually sounds… hopeful! I do a simple find/replace in the rake task code, changing “fastercsv” to “csv” and “FasterCSV” to “CSV” — and it works like a charm! We’re in business. I export my main model to CSV and upload it to Google Docs. I remove a few fields (autogenerated id and the created_at/updated_at timestamps) and add the column types into the second row for reference purposes; now we have a spreadsheet import template we can just clone off to add data as needed. Allons-y!
I check in the changes (commit -am ‘message here’) and receive a funny message:
# On branch csvIOTask # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # (commit or discard the untracked or modified content in submodules) # # modified: lib/tasks/database (modified content) #
Git is seeing the cloned “database” repository as a submodule of sorts. (More specifically, it’s reading the .git in that directory.) Since I didn’t add it properly as a real submodule, I can’t just hide the changes and go about my merry way. I eventually just remove the .git directory from /lib/tasks/database, and that fixes the problem as well.
Data import/export is up and running! Next time, I’ll be working through our authentication model.