Been Born Yet – Creating a Rails Application for the first time

About three months ago I started to work on my first Ruby on Rails application. As the annoying “more of a designer than a developer” type of web person, I’ve always felt reliant on developer friends and colleagues in order to build anything more than static HTML/CSS & Javascript. While I acknowledge that I’m not an excellent developer, I felt a little impotent not knowing enough to hold conversation or do basic things. More importantly, I also wanted to be able to actually act on ideas for applications that kept springing into my head without having to rely on anyone else (unless, of course, I wanted to go into a partnership).

Building Been Born Yet in Ruby on Rails was my way of learning enough to have the confidence to try slightly more aggressive things in the future. In this post, I hope to be able to explain the process I’ve gone through in the hope it will make it easier for others who are interested in doing the same thing.

Why Been Born Yet?

I’ve tried to build a Rails application before, but I think the key difference this time was motivation. My wife and I are about to have a baby (due tomorrow actually) so it seemed that something to do with babies would be advantageous. Having seen http://hasasteroidwonderlandbeenborn.heroku.com/ from a friend at work, I thought I could build on this idea and turn it into a handy web app for people who wanted to be able to tell friends, family and co-workers when their child was born.

What does it do? 

Been Born Yet does two simple things.

1. It allows people to create a customised landing page (which they can share with anyone) which lets others know if their child has been born yet. Friends and family can visit this page and sign up to be told when the baby is born.

2. Once the baby is born, parents can simply login, provide basic details about their new child and all of the waiters will automatically be notified by email.

Everything that the app does other than this is complexity that I didn’t have to have. Extra features you see on the site now are additions I’ve made as I though they sounded cool.

What’s in V1?

Having read Eric Ries’, “Lean Startup“, I was very keen to make sure I didn’t muck around and released a Minimum Viable Product (MVP) as quickly as possible. This would let me learn whether or not this is something people would use. Having started many apps and online business ideas before (many with Michael Morris), I was sick of wasting countless hours of valuable personal time without actually having anything live to show for it. A string of registered, yet unused domain names was enough motivation for me to keep things as basic as possible to start with.

For me that meant the following:

  • I cut anything I could (for example, the site originally launched without sub-domains supported)
  • I did not allow myself to do any front-end design until the site was mostly functional (The purpose of this project was to release something that worked and helped me learn to program in Rails. I do need to get better at web design as well, but that’s was not what my primary objective is for this project
  • I started with plenty of time to spare
  • I asked the incredibly generous friends and the rails community for help after I’d spent a minimum of a few nights looking for an answer myself
  • I used Heroku for hosting rather than potentially less expensive for convenience and speed
  • I used gems to provide functionality rather than re-inventing the wheel (although, Devise may have actually slowed me down in retrospect).

The fact that our babies due date is relatively fixed didn’t hurt either, as it forced me to focus and get something up in time to let our friends know. I’d strongly suggest that if you’re looking to start a project that find and set some sort of deadline. Find ways to make it fixed.

What to do first

To get my head around the basics, I used a few great online resources:

  • RailsTutorial.org (I had used this previously to try and complete the lengthy tutorial, but never finished)
  • TeamTreehouse (aka ThinkVitamin) – excellent video resources
  • Rails For Zombies (especially the slides – they were amazing as a cheat sheet)

I also set myself up using BitBucket (I use github at work, but it is a little expensive for private repositories) so that I could work across multiple computers easily.

One of the best things about working using git is that I can look back through my commit history and see how I pieced things together. I made sure to write quite descriptive commit messages mainly so that I could cement in my head what I was doing.

By thinking through what I wanted my site do to, I realised that I needed three Models:

  • Babies
  • Parents
  • Waiters

Parents could have many babies (who belonged to a parent), Babies could have many waiters (who belonged to a baby). It took me quite a few tries to get these associations working properly (especially once devise came into the picture to authenticate parents), but one of the advantages of working using git in conjunction with the free BitBucket.org repository hosting was that I could create new branches to try and get a new feature working. If I got stuck, I could swap to a different branch and work on something else for a few days while I had a chance to think the problem over. It was amazing how many things clicked into place overnight once I had time to think the problem through a little more.

Slow, gradual progress

Once I had this basic structure mapped out, I could take things one step at a time. Initially I begun by only adding parents and babies – waiters could come later (they were a non-essential feature as the site could work without them). Authentication, notification emails etc, could all come later. Once I was confident that each piece was working correctly I added a new one.

A good example of this is that although it was tempting to try and add authentication straight away, I knew this would be a bit tricky, so only once Parents could create babies properly did I try and retrofit Devise authentication into the equation (Note: Devise actually made things really tricky, especially once subdomains were added into the equation).

One of the things I found most difficult about the process was figuring out what to do next. Keeping a README.mdown in my project was a really great place to create a to-do list of bite-sized tasks I could add. Throughout I made sure that there were two parts to the list, things that HAD to be done before the site was functional, and things that were OPTIONAL and could wait until after launch. After that, my nightly routine was to open up the project, look at the to-do list and brute force my way through the problems until I got stuck. I’d then either try and find decent tutorials via google, or, if things got really bad after a few days, reset HEAD to a stable point and start again. Using branches was helpful here (most of these were only local branches). Sometimes I just had to ask for help and this was an excellent experience.

You can see my initial commits below (for those who are interested, I’ve uploaded screenshots of all of my commits into the gallery below):

Asking for help

Perhaps the nicest part of building this app has been discovering just how awesome people are if you are gracious and ask nicely. The Rails community in Melbourne has been so helpful. Each time I’ve been genuinely stuck on a part of my app, there have been several people (especially via twitter) who have been happy to help.

Throughout, a combination of the tools below has made it really easy to find and ask for help when I got really stuck.

  • Twitter – If you have the right twitter followers, Twitter is perhaps the most powerful way to get help in conjunction with a well prepared question or gist. It is especially useful for recommendations about the right gem to use for different purposes or to find out what to search for to solve your own problem. Often finding the right search term is half the battle
  • Stack overflow – great for asking questions and finding excellent answers. The voting mechanisms mean it is easy to identify which answers others have found most useful. Be sure to let people know if their answer has helped you.
  • Friends (Michael helped me with some of the harder bits (subdomains were tricky). To make the most of his time, I came prepared with a list of 3 things I couldn’t quite crack and we got through them really fast)
  • Gist (part of github, gist lets you share snippets of code and is very handy)

A word of caution to the lazy. As a n00b developer, I’m very aware of the fact that I need to ask for a lot of help – it’s partly the idea of reducing that reliance that drives me to want to learn more in the first place. It’s important to be aware that other people don’t have to help you and to respect their time. I only asked for help after I’d spent a good few days banging my head against a wall and trying to find a solution myself. If you don’t try and learn independently (using tools like stackoverflow and google) you won’t get anywhere.

Launch before you feel comfortable

Fortunately for me, I felt some very real pressure to get the site live. If I didn’t have the site live at least 4 weeks before the due date of our baby (28/12/2011) there was a very real chance that we wouldn’t get a chance to actually use the site for our baby at all. This was excellent as it meant that I was forced to put the site live before I felt like it was completely ready.

On the night beenbornyet was deployed, I realised I wasn’t happy with the design and that there were many features not yet in place. I had only spent a few hours designing the site as I promised myself I wouldn’t spend much time here. It felt very raw (& still does). I spent 30 minutes just before launch hacking out css to come up with the much simpler design you see now as I thought it would be easier to maintain than the original design. It could be improved, but I can do that later.  When you look at the design of forums like Essential Baby (which is an excellent pregnancy resource btw) you realise that design is really not driving use. The key was to SHIP IT!

When first launched, the site:

  1. Did not allow for subdomains (eg. has[babyname].beenbornyet.com) – URLs were in the form http://beenbornyet.com/babies/23
  2. Did not send notification emails of any kind, or use background workers to improve performance
  3. Did not allow people to upload photos of their child, or store those images on AWS S3
  4. Did not work on a mobile devices

In retrospect, this the best thing that could’ve happened. My wife put a notice out on her Pregnant Mum’s forum (Essential Baby) and people started using it straight away.

Seeing people use what you have created is the single greatest form of motivation

As soon as the site was up, the forum started to send traffic to it. It’s a gimic, but having Google Real-Time on is an incredible way to motivate yourself once you’ve unleashed your baby into the world. Straight away you start to think of ways to improve things, and best of all, the people actually using your site will start to think of things they’d like you to add. Make it easy for them to contact you. 

Where to next?

Since launching the site over 50 unique have been babies listed, including Baby Jesus (http://hasjesus.beenbornyet.com). For me, this shows that the basic concept is working and that more people will likely use the app if I:

  1. Add features that make the app easier and more useful
  2. Promote it well so that people know about it

Although the site was originally just a development challenge, now that I’ve made something that could have legs, I’m keen to learn as much as I can from a promotional perspective as well.

New features

To acheive these two things I’ve written myself a list of new features I’d like to add. As well as things that are basic UX/UI improvements (like sending notification emails), there are also things that will stretch my skills on this list from a development perspective

  • SMS integration (I want to use Moonshadow to allow waiters to sign up to be notified by SMS – given the site has an international audience, this could be a little tricky).
  • Reminder emails (to make it so that if a parent has a Baby with waiters, they are reminded before and after the due date to let everyone know)
  • Notification card (It might be cool to integrate the site with an easy and innexpensive way to have little notification cards printed and delivered.
  • Add the ability to upload ultrasound photos or videos to waiting pages like http://hascletus.beenbornyet.com
  • Add the ability for the app to remove babies that have been around for a while to free up the subdomain address (currently these have to be unique)
  • Add validation for waiter and parent email addresses
  • Add social network sharing buttons to improve referrals
  • Add a testing framework (I’ve been naughty / ignorant and haven’t invested the time required to do TDD, but given that the app is still relatively simple, retrofitting one shouldn’t be too hard…I hope)
  • DONE: Use background workers to send emails (sending large numbers of emails to waiters currently makes the app slow right down while these are all processed. I want to learn how to use background workers to take this load and free up my Web Dynos.)
  • DONE: Keeping costs contained  (Heroku is great, but it quickly becomes expensive. Currently I’m spending $40/month on something that doesn’t make me any money. I don’t mind paying it, but it’d be great to learn how to reduce costs and make use of Heroku’s cloud based dynamic scaling abilities)
I’m sure I’ll find other things that I want to add, or that people ask me to put in.

Promoting the app

Now that I’ve built the app and it’s functioning in some form the next challenge is to promote it. Not really the point of this post, but it’s important to mention, as I’ve seen many people build a website and then assume that their work is done. Unless you’re facebook, this is hardly the case. More on this in another post.

Anyway, I hope this post is useful – one day out from the due date, hopefully over the next few days I’ll be able to swap the “No” to a “Yes”.

Thanks again to everyone who has helped me pull this app together.