Page 2 of 4

Previous page

Talk: Asynchronous Collaboration Nov 9, 2012

MALMÖ, SWEDEN — Øredev Developer Conference 2012 — Communicating Through Our Source Code. We hear a lot about how strong communication and collaboration are key to a successful project. We spend a lot of time focusing on stand-up meetings and pair programming, but there are potentially other very effective means of keeping the team on the same page that not only avoid daily interruptions but also provide long-term benefit.

The goal of this talk is to help your team improve its own collaboration and productivity with just a bit of discipline and relatively low overhead.

Watch the Video [vimeo]

Disable Chrome's Print Dialog and Use the OS X System Dialog Instead Sep 13, 2012

I really dislike the custom print dialog that ships with Google Chrome nowadays (Chrome is currently at v21 at the time of writing). By itself, it’s not terrible, but I want my print dialog to look like every other darn print dialong on OS X, gosh dammit.

Google Chrome's Print Dialog

When Google first introduced the new print dialog, Chrome also included a custom setting to disable it under about:flags, but in v20, Chrome removed the ability to disabled the print dialog.

There are a couple workarounds on the internet like starting Chrome with an --args --disable-print-preview, but that’s not too feasible under normal conditions. Other solutions recommend using ⌘⌥P or hold down Option () when accessing the File menu, but who wants to remember to use a different keyboard shortcut for just one application?

Fortunately, OS X comes with a relatively simple way to override keyboard shortcuts in specific Applications. Go to System Preferences -> Keyboard -> Keyboard Shortcuts. Once there, select Application Shortcuts and add a new shortcut for Google Chrome.

Override for Chrome's Print Shortcut

Make sure the Menu Title reads Print Using System Dialog... exactly, and give it the standard print shortcut (⌘P).

New Chrome Print Shortcuts

Enjoy! Happy Printing!

UPDATE: There’s another workaround that’s relatively painless and works well. Open up Terminal and override the setting at the command line:

defaults write com.google.Chrome DisablePrintPreview -boolean true

This works, but also completely disables the Chrome print dialog altogether, so there’s no way to use it with a different keyboard shortcut in case you want to test the default behavior that most others experience.

MongoDB Schema Design at BusyConf Jun 5, 2012

This post is in response to the 10gen MongoDB Schema Design Contest. It was also extracted from talks that I’ve given on the subject.

UPDATE: MongoDB awarded this entry the grand prize in the design contest.

Obligatory Plug

BusyConf currently handles 4 major pieces of conference planning – it collects speaker proposals, allows the review committee to rate speaker proposals, builds an offline-enabled and archived HTML5 schedule (iPhone, Android, iPad, Desktop), and handles attendee ticket registration including payments, refunds, etc.

We attend conferences, and as attendees, the schedule at the conference is often lacking. It’s poorly organized, lacks information, and requires Internet access. This makes it hard as an attendee to choose the talks that you want to go to. BusyConf is an attempt to solve that problem while also making it easier for conference organizers to run a conference. We handle the calls for proposal, we allow organizers to rate proposals, we give them an interface to turn activities into a schedule, and we publish that schedule in many formats. We also handle ticket registration and credit card payments.

Why MongoDB?

MongoDB was a huge win for us while designing our application. The goal of this post is to explain why we chose MongoDB, how we use it at BusyConf, what design decisions we considered, and what the alternatives might have been.

Here’s a common myth that I’ve heard before: “MongoDB design is easy because its schema-less.” I disagree with this. It’s true that a thoughtful design will yield a longer term gain in easier development, but it can be tricky to conjure up with such a design. I find it much easier to get a relational design right the first time, but the costs of maintaining a relational design can sometimes be higher.

“You could use a relational database for that! Why use a document store?”

MongoDB’s speed and scalability are wins, but for us, it’s not as important as the win we get from rapid development. Rapid development comes from the ability to represent richer data models that more closely match the business problems and the patterns of access.

Many people say things like: “You could use a relational database for that! Why use a document store?” MongoDB has become our default database for greenfield development. We now make ourselves justify the use of relational. Instead of, “Why MongoDB?” we ask, “Why NOT MongoDB?”

The Logical Model

This post only covers the design of our database that represents a conference schedule. The data model that represents a conference schedule is roughly a tree – very nested. Imagine a typical conference or convention that you attended in the past. Events have days, days have tracks, tracks have time slots, time slots have activities, and activities have speakers. In addition, days can also have global time slots (like Lunches, Breaks, and Keynotes).

BusyConf Logical Model

When we access our data for rendering a schedule, we need to pull all of this at once, because we want a seamless, cached experience for the conference attendee.

The Relational Option

What might the above logical model look like in a relational database? The nice thing about a relational model is that they are fairly easy to design. This is how we might have modeled our data given a relational database.

BusyConf Relational Model

What kind of queries would be required to pull all the data from this design?

It looks pretty straight forward until you imagine having to pull all this data at once to render a full schedule. What kind of query or queries would be required from a relational database? Would you use one big nasty join, or lots of individual queries? Neither seem like a great option.

To add to the problem, little things like the position of tracks are not easily represented. Neither is the potential explosion of meta data that could come from each object.

First Attempt with MongoDB

Representing our logical model directly within MongoDB was our first instinct, BUT putting this into practice actually led us down a road of unnecessary complexities:

BusyConf MongoDB Model - First Attempt

This first attempt was a mistake.

While we solved the problem of quickly accessing the entire event, we no longer have an easy way of accessing an individual activity or speaker. We can quickly see the complexities in the drawing above.

Current Design with MongoDB

We iterated on the design many times, but in the end, we took a fairly unique approach.

BusyConf MongoDB Model - Current Design

Instead of one collection, we broke out Activities and Speakers.1 This matched our patterns of access much better. Instead of deeply nesting every object, we chose to embed arrays of days, tracks, and time slots immediately under the event document.

Each object has a unique ID. Everything is more easily addressable, because we have less nesting. The logical model is represented with pointers from one nested document to another. Of course, we don’t actually see our logical model until we piece it together on the client side, but that is okay because we don’t need the full logical model until until we put the leg work in to render the schedules in the browser.

Conclusion

MongoDB can be somewhat tricky when it comes to the up front design, but if done right, it has some great benefits both in defining and matching your unique access patterns along with fairly decent long-term maintenance benefits.

  1. Later, we decided to embed Speakers under Activities to improve our patterns of access, but ironically, we plan to switch Speakers back out to their own collection again to provide cleaner normalization. 

Reserving Subdomains in Your Multi-Tenant Web Application May 7, 2012

It’s fairly common to segment the accounts in your multi-tenant application with subdomains. GitHub gives you a subdomain that matches your username (e.g. rmm5t.github.io). Freshbooks gives you a subdomain that matches your company name (e.g. busyconf.freshbooks.com). At BusyConf, we give you a subdomain that matches your conference name (e.g. railsconf2012.busyconf.com).

Your customers usually get to choose their own subdomain during account sign-up, and when developing a subdomain-based multi-tenant application, it easy to forget to reserve some common subdomains for your own use and future growth. There’s nothing like trying to register a new service only to realize that one of your customers already has the subdomain that you had hoped to use.

It’s a good idea to make a list of subdomains that you don’t want your customers to use. Here’s a list of subdomains that I like to reserve in my multi-tenant applications:

admin, api, assets, blog, calendar, camo, dashboard, demo, developer, developers, docs, files, ftp, git, imap, lab, m, mail, manage, mx, pages, pop, sites, smtp, ssl, staging, status, support, www

What subdomains are missing from this list?

In terms of an ActiveModel validation in Rails, that looks something like this:

RESERVED_SUBDOMAINS = %w(
  admin api assets blog calendar camo dashboard demo developer developers docs files ftp git imap lab m mail manage mx pages pop sites smtp ssl staging status support www
)
validates_exclusion_of :subdomain, :in => RESERVED_SUBDOMAINS,
                       :message => "Subdomain %{value} is reserved."

Talk: Just In Time Inventory with Spree Feb 16, 2012

NEW YORK, NY — SpreeConf 2012 — In this talk, we will not only explore what it takes to extend Spree, but we will also experiment with the notion of using it to build our products on demand. We will take Spree, slap a MakerBot on the backend, build some extensions, and build a store that automatically prints products only after an order is placed.

Were you there? Please rate my talk.

Here’s the montage video that was shown during the presentation.

Talk: HTML5 Application Caching Feb 2, 2012

MCLEAN, VA — MoDevDC — At BusyConf, we leverage offline application caching so your schedule is available even after losing an internet connection.

Caching can be hard, and the application cache can be a bit confusing to wrap your head around. This talk tries to bring a little bit of sanity to that area.

How To Add a DNSimple SSL Certificate to Heroku Sep 16, 2011

DNSimple has some of the best prices on SSL certificates. If you have a DNSimple account, perfect, you already know how useful it is. If not, go sign up now, and then come back.

1. Buy an SSL Cert from DNSimple

The first thing to do is to buy an SSL cert from DNSimple (I usually only buy wildcard certs nowadays). Go to the manage interface for the domain that you want to buy the SSL cert, and click “Buy an SSL Certificate.” The interface will walk you through the rest of the steps. As long as you’re not super paranoid, you can even let DNSimple generate the private key and certificate signing request for you. Don’t worry, you can delete the private key from the DNSimple servers immediately after you save it to a secure place.

After a few minutes, you should receive some emails with your new SSL cert (a resulting wildcard certificate will actually come from Comodo).

2. Build the Public Certificate Chain PEM file


UPDATE: If you downloaded the certificate chain directly from Comodo, the steps below are necessary; however, now if you log back into DNSimple, they now perform this nonsense for you automatically. Just download the pre-concatenated certificate bundle and private key directly from DNSimple and follow the instructions for adding or updating your cert (i.e. Skip to step 3). Thanks DNSimple!


Along with your SSL certificate, Comodo will send a zip file containing the Root CA Certificate and some Intermediate CA Certificates. Before we can upload our certificate to Heroku, we need to concatenate these files together to form the certificate chain.

cat STAR_yourdomain_com.crt EssentialSSLCA_2.crt   \
    ComodoUTNSGCCA.crt UTNAddTrustSGCCA.crt        \
    AddTrustExternalCARoot.crt > STAR_yourdomain_com.pem

Make sure you concatenate these files in the correct order, starting with your cert and ending at the root cert; otherwise, Heroku will not be able to recognize the result as a public key certificate.

This example shows the chain for a wildcard certificate (from Comodo). Your chain might be different if you purchased a single subdomain certificate from DNSimple (I think those come from RapidSSL, which might deliver root certs).

Note: To make sure Heroku can automatically start your server, you must not have a passphrase assigned to the certficate. If you let DNSimple do all the work for you, you should already have a passphrase-free cert.

3. Add the SSL Endpoint Add-on to Your App

heroku addons:add ssl:endpoint

Read more about the SSL Endpoint Add-on.

4. Upload your SSL Cert and Private Key to Heroku

heroku certs:add STAR_yourdomain_com.pem STAR_yourdomain_com.key

That’s it! You can find more information and instructions on what to do after this from the Heroku Dev Center.

If you instead need to update an existing cert, use the cert:update command. This prevents you from having to update your DNS settings:

heroku certs:update STAR_yourdomain_com-bundle.pem STAR_yourdomain_com.key

Lightning Talk: Do Your Commit Messages Suck? Sep 2, 2011

BOULDER, CO — Rocky Mountain Ruby 2011 — Software projects are collaborative. They usually encompass many months or years and are touched by several developers along the way.

Communication is key to any good software project. Strong, well written, commit messages are one way to increase communication and documentation with very little overhead.

The project history plus a strong blame engine give us the power to answer future questions about what we were thinking at the time something was added or changed.

Watch the Talk

Download the Slides [PDF 7.8 MB]

Were you there? Please rate my talk.

Next page