Sam Soffes

Behind Cheddar’s Server

Posted on

So, tech doesn't matter. Tech is interesting though. Here's some of what I use to make Cheddar's server. A lot of Cheddar is on the server. I've spent way more time writing Ruby than writing Objective-C when it comes to Cheddar.

The Cheddar web app is written in Ruby on Rails. I choose Ruby on Rails because I already have a lot of experience with it and it let's me work quickly.

For awhile, the API and the web app were two separate Rails apps. The web app simply used the API. This quickly became hard to manage and test. I ended up merging them back together before launching. The API is still very separate from the web app. At some point, I would like to split it out once I have more time to work on my internal tools.

All of the realtime aspects are powered by Pusher. I considered building something from scratch to do all of this, but was focused on shipping. At some point, it would be easy for me to replace Pusher with my own stuff, but honestly they are awesome and very affordable. I doubt I ever will.

All of the API documentation I did from scratch. I wrote a little Ruby gem to do code coloring and truncation of example responses the way I wanted called Pizzazz. I really love Stripe's API documentation. They use your real data in all of the examples and give you example commands for each method. It was actually a lot easier than I thought to implement this and people seem to really like it.

All of the OAuth stuff I did from scratch as well. There are a few solutions out there but I started to spend more time customizing them than it would take to write my own. I've written OAuth clients and servers before so it wasn't a big deal.

The tasks and lists view uses Backbone.js (in conjunction with Pusher) to make everything feel really instant. All of the JavaScript for Cheddar is written in CoffeeScript and all of the CSS is written in SCSS.

Here's my Gemfile. I added lots of comments so you can see what everything is for.

source 'https://rubygems.org'

# The latest version of Ruby
ruby '1.9.3'

# The lastest version of Rails
gem 'rails', '3.2.6'

# Postgres
gem 'pg'

# EventMachine-based web server
gem 'thin'

# Backbone adapter
gem 'backbone-on-rails'

# Easily send Ruby to JavaScript in views
gem 'gon'

# Hashtag and autolink parsing
gem 'twitter-text'

# Emoji detection
gem 'named_emoji'

# Encrypt passwords
gem 'bcrypt-ruby'

# Sending email
gem 'postmark-rails'

# Ordering of lists and tasks
gem 'acts_as_list'

# Easy seeding of the database without duplicates
gem 'seed-fu'

# Payment processor
gem 'stripe'

# Used for list slugs
gem 'base32-crockford', require: 'base32/crockford'

# Networking. Mainly for verifying iTunes receipts
gem 'httparty'

# Memcache client. Used for various caching
gem 'dalli'

# Key-value store client. Used for some caching
gem 'redis'

# Pretty API docs
gem 'pizzazz'

# Sidekiq queueing system and dependencies
gem 'sidekiq'
gem 'slim'
gem 'sinatra', :require => nil

# Pusher and dependencies
gem 'em-http-request'
gem 'pusher'

# For the Asset Pipeline
group :assets do
  # Pre-release of SASS for @media
  gem 'sass', '>= 3.2.0.alpha.261'

  # SASS Rails integration
  gem 'sass-rails'

  # SASS awesome mixins
  gem 'bourbon'

  # Simple CSS grids
  gem 'grater'

  # CoffeeScript Rails integration
  gem 'coffee-rails'

  # jQuery
  gem 'jquery-rails'

  # JavaScript compressor
  gem 'uglifier'
end

# Only used in development
group :development do
  # Manage multiple processes
  gem 'foreman'

  # Heroku and dependencies
  gem 'heroku'
  # gem 'taps'
  # gem 'sqlite3'

  # Open emails in development
  gem 'letter_opener'

  # Hide asset requests from developmenet logs
  gem 'quiet_assets'

  # Scan for security issues
  gem 'brakeman'
end

# Only used for testing
group :test do
  # Simple factories
  gem 'miniskirt', require: false

  # Generate dummy data
  gem 'faker'

  # Fantastic tests
  gem 'minitest'

  # Color test output
  gem 'minitest-wscolor'

  # Test Rack requests
  gem 'rack-test', require: false

  # Mock external libraries
  gem 'mocha', require: false

  # Simulate the browser
  gem 'capybara', require: false

  # Work with cookies while testing
  gem 'show_me_the_cookies'

  # Test coverage analysis
  gem 'simplecov', require: false

  # Simple test runner (my fork fixes MiniTest integration)
  gem 'm', git: 'https://github.com/soffes/m.git', require: false
end

# Only used in production
group :production do
  # Reporting
  gem 'newrelic_rpm'

  # Easy SSL redirection for certain paths
  gem 'rack-ssl-enforcer'

  # Exception reporting
  gem 'exceptional'

  # Limit requests to 30 seconds
  gem 'rack-timeout'
end

Everything is hosted on Heroku. I use Heroku Postgres for the database, their memcached add-on, and the RedisToGo add-on. Here's a recent post about lessons learned while scaling.

Update 06/22/2013: I no longer own Cheddar. More info.