Saturday, June 15, 2013

Tutorial - How to Deploy Ruby on Rails with Heroku, mySQL, and Amazon S3

    So I haven't blogged about my experiences with computer science development yet, but lately I've been working a lot with trying to deploy a small Rails application and decided to write about it. I have never deployed before, and as a beginner its been a nightmare. I figured that hopefully my issues and solutions can be of some help to developers out there.

    Basically, I have a small rails application that I want to have live. The app itself runs on mySQL and has an upload functionality where users can upload files and also download files that other users upload. I did this through the Paperclip gem. So I needed a server to host a small amount of files as well as my app. I decided to look into cloud based application platforms, specifically Amazon Web Services, or AWS. AWS is great because its scalable and you only pay for what you use. I only really needed to host small files, so this was perfect.

    The first look at Amazon AWS is extremely daunting, they have a ton of different services, and honestly I barely know what any of them mean. After a bit of googling I found that my best option was EC2, which would have supplied workers for my application as well as file storage. I think this is how it would have worked, as I didn't end up using EC2 as you'll read and I'm still not quite sure how it works. But I tried to deploy to EC2 first manually, then using a gem called Rubber, and kept running into a lot of different issues. I figured there had to be a better way. And thankfully, I found Heroku.

    Heroku is a cloud based application platform for a few different languages, including Ruby on Rails. It is hooked up to Git, so basically all you really need to do is make a Heroku account, log in on your local machine, and push your code to a new git branch called Heroku. Thats it. It is insanely easy.

    Heroku uses workers that they call dynos. Your first dyno is free, which is great because my small app that I only use for personal purposes didn't need very much power. Small app, personal use, easy deployment, rails supported, free usage - Heroku was truly a godsend.

    However, Heroku by itself does not have storage services, and I needed somewhere to place files that are uploaded by users. I quickly found Amazon S3, which is nothing more than a fast and secure file storing service. S3 offers 5GB of storage, 20,000 GET requests, and 2,000 PUT requests for free. Free Heroku with free Amazon S3 storage - it quickly looked like I was going to be able to get my app in production 100% free of charge, which was great! So here are the steps I took to deploy to Heroku and link my Heroku app to Amazon S3.

First, visit Heroku.com and create an account with them. Then download the Heroku Toolbelt so you can use their terminal commands. Download here.

After the toolbelt is downloaded, then you can log in on your local machine.

 anthony$ heroku login  
 Enter your Heroku credentials.  
 Email: to.anthony93@gmail.com  
 Password (typing will be hidden):  
 Found existing public key: /Users/anthonyto/.ssh/id_rsa.pub  
 Uploading SSH public key /Users/anthonyto/.ssh/id_rsa.pub... done  
 Authentication successful.  

If you did not have public ssh keys already generated, there are instructions here. This public key is used to link your local machine and your Heroku app to your remote Github account. Once this is done, you can try to deploy your application to Heroku. Make sure that you have already committed and pushed all changes on your local machine to your master branch before you deploy to Heroku. As I said earlier, deploying to Heroku is as easy as pushing to GitHub. So upon the first time I try to deploy to Heroku:

 anthony$ git push heroku master  
 Warning: Permanently added the RSA host key for IP address '50.19.85.154' to the list of known hosts.  
 Counting objects: 233, done.  
 Delta compression using up to 4 threads.  
 Compressing objects: 100% (219/219), done.  
 Writing objects: 100% (233/233), 974.57 KiB | 129 KiB/s, done.  
 Total 233 (delta 81), reused 0 (delta 0)  
 -----> Removing .DS_Store files  
 -----> Ruby/Rails app detected  
 -----> Installing dependencies using Bundler version 1.3.2  
     Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin --deployment  
     You are trying to install in deployment mode after changing  
     your Gemfile. Run `bundle install` elsewhere and add the  
     updated Gemfile.lock to version control.  
     You have added to the Gemfile:  
     * source: git://github.com/wr0ngway/graylog2_exceptions.git (at master)  
     * paperclip  
     * therubyracer  
     * rubber  
     * open4  
     * gelf  
     * graylog2_exceptions  
     * graylog2-resque  
     You have changed in the Gemfile:  
     * graylog2_exceptions from `git://github.com/wr0ngway/graylog2_exceptions.git  
     (at master)` to `no specified source`  
  !  
  !   Failed to install gems via Bundler.  
  !  
  !   Heroku push rejected, failed to compile Ruby/Rails app  
 To git@heroku.com:dry-taiga-2649.git  
  ! [remote rejected] master -> master (pre-receive hook declined)  
 error: failed to push some refs to 'git@heroku.com:dry-taiga-2649.git'  

It turns out this error had to do with my Gemfile.lock file, since I had tried Rubber earlier and removed the gem. The fix was basically to delete the Gemfile.lock file and run bundle. This regenerates a Gemfile.lock. Keep in mind that in order for Heroku to work in production, if you make any changes to your Gemfile at all you must delete your Gemfile.lock, run bundle to renegerate your Gemfile.lock, then you can deploy to Heroku. Now:

 anthony$ git push heroku master  
 Counting objects: 243, done.  
 Delta compression using up to 4 threads.  
 Compressing objects: 100% (229/229), done.  
 Writing objects: 100% (243/243), 975.77 KiB | 125 KiB/s, done.  
 Total 243 (delta 87), reused 0 (delta 0)  
 -----> Removing .DS_Store files  
 -----> Ruby/Rails app detected  
 -----> Installing dependencies using Bundler version 1.3.2  
     Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin --deployment  
     Fetching gem metadata from http://rubygems.org/..........  
     Fetching gem metadata from http://rubygems.org/..  
     Installing rake (10.0.4)  
     Installing i18n (0.6.4)  
     Installing multi_json (1.7.4)  
     Installing activesupport (3.2.6)  
     Installing builder (3.0.4)  
     Installing activemodel (3.2.6)  
     Installing erubis (2.7.0)  
     Installing journey (1.0.4)  
     Installing rack (1.4.5)  
     Installing rack-cache (1.2)  
     Installing rack-test (0.6.2)  
     Installing hike (1.2.2)  
     Installing tilt (1.4.1)  
     Installing sprockets (2.1.3)  
     Installing actionpack (3.2.6)  
     Installing mime-types (1.23)  
     Installing polyglot (0.3.3)  
     Installing treetop (1.4.12)  
     Installing mail (2.4.4)  
     Installing actionmailer (3.2.6)  
     Installing arel (3.0.2)  
     Installing tzinfo (0.3.37)  
     Installing activerecord (3.2.6)  
     Installing activeresource (3.2.6)  
     Installing climate_control (0.0.3)  
     Installing cocaine (0.5.1)  
     Installing coffee-script-source (1.6.2)  
     Installing execjs (1.4.0)  
     Installing coffee-script (2.2.0)  
     Installing rack-ssl (1.3.3)  
     Installing json (1.8.0)  
     Installing rdoc (3.12.2)  
     Installing thor (0.18.1)  
     Installing railties (3.2.6)  
     Installing coffee-rails (3.2.2)  
     Installing jquery-rails (2.2.1)  
     Installing mysql2 (0.3.11)  
     Installing paperclip (3.4.2)  
     Using bundler (1.3.2)  
     Installing rails (3.2.6)  
     Installing sass (3.2.9)  
     Installing sass-rails (3.2.6)  
     Installing uglifier (2.1.1)  
     Your bundle is complete! It was installed into ./vendor/bundle  
     Post-install message from rdoc:  
     Depending on your version of ruby, you may need to install ruby rdoc/ri data:  
     <= 1.8.6 : unsupported  
     = 1.8.7 : gem install rdoc-data; rdoc-data --install  
     = 1.9.1 : gem install rdoc-data; rdoc-data --install  
     >= 1.9.2 : nothing to do! Yay!  
     Post-install message from paperclip:  
     ##################################################  
     # NOTE FOR UPGRADING FROM PRE-3.0 VERSION    #  
     ##################################################  
     Paperclip 3.0 introduces a non-backward compatible change in your attachment  
     path. This will help to prevent attachment name clashes when you have  
     multiple attachments with the same name. If you didn't alter your  
     attachment's path and are using Paperclip's default, you'll have to add  
     `:path` and `:url` to your `has_attached_file` definition. For example:  
     has_attached_file :avatar,  
     :path => ":rails_root/public/system/:attachment/:id/:style/:filename",  
     \   :url => "/system/:attachment/:id/:style/:filename"  
     Cleaning up the bundler cache.  
 -----> Writing config/database.yml to read from DATABASE_URL  
 -----> Preparing app for Rails asset pipeline  
     Running: rake assets:precompile  
     Asset precompilation completed (18.11s)  
 -----> Rails plugin injection  
     Injecting rails_log_stdout  
     Injecting rails3_serve_static_assets  
 -----> Discovering process types  
     Procfile declares types   -> (none)  
     Default types for Ruby/Rails -> console, rake, web, worker  
 -----> Compiled slug size: 10.2MB  
 -----> Launching... done, v6  
     http://dry-taiga-2649.herokuapp.com deployed to Heroku  
 To git@heroku.com:dry-taiga-2649.git  
  * [new branch]   master -> master  

All good! Now my code is deployed to Heroku. The next step is to start a dyno, then I can visit my app. At my first attempt to start up my Heroku dyno:

 anthony$ heroku ps:scale web=1  
 Scaling web dynos... done, now running 1  

Looks good, but when I check the status of this dyno:

 anthony$ heroku ps  
 === web (1X): `bundle exec rails server -p $PORT`  
 web.1: crashed 2013/05/28 17:28:28 (~ 13s ago)  

Looks like it crashed. And when I run "$Heroku open" to check my application, it gives me a bad webpage. I later found out that this was because my app was currently using mySQL, and Heroku is defaulted to use PostgreSQL. At this point I had two options. I could choose to migrate my application database to PostgreSQL or to use a Heroku add-on to make my existing mySQL app work. The Heroku website encourages the use of PostgreSQL because it was built to work best with PostgreSQL. But as I looked into migrating, even getting PostgreSQL installed on my computer was a hassle. Heroku provides an easy download called PostgreSQL.app for OSX users, but this only works on 10.7 (lion) or above. I run 10.6.8 (Snow Leopard), so this was not an option. I went ahead and tried to download PostgreSQL using Homebrew, and ran into even more problems that looked like this:

 anthony$ brew install postgresql  
 Warning: It appears you have MacPorts or Fink installed.  
 Software installed with other package managers causes known problems for  
 Homebrew. If a formula fails to build, uninstall MacPorts/Fink and try again.  
 Error: /usr/local/opt/readline not present or broken  
 Please reinstall readline. Sorry :(  

I uninstalled Macports (which isn't as good as Homebrew anyways), and still get the same error. I uninstalled and reinstalled readline and get an error:

 anthony$ brew install readline  
 ==> Downloading http://ftpmirror.gnu.org/readline/readline-6.2.tar.gz  
 Already downloaded: /Library/Caches/Homebrew/readline-6.2.4.tar.gz  
 ==> Patching  
 patching file callback.c  
 patching file input.c  
 patching file patchlevel  
 patching file support/shobj-conf  
 patching file vi_mode.c  
 ==> ./configure --prefix=/usr/local/Cellar/readline/6.2.4 --mandir=/usr/local/Cellar/readline/6.2.4/share/man --infodir=/usr/local/Cellar/readline/6.2.4/share/info --enable-multi  
 ==> make install  
 ==> Caveats  
 This formula is keg-only: so it was not symlinked into /usr/local.  
 OS X provides the BSD libedit library, which shadows libreadline.  
 In order to prevent conflicts when programs look for libreadline we are  
 defaulting this GNU Readline installation to keg-only.  
 Generally there are no consequences of this for you. If you build your  
 own software and it requires this formula, you'll need to add to your  
 build variables:  
   LDFLAGS: -L/usr/local/opt/readline/lib  
   CPPFLAGS: -I/usr/local/opt/readline/include  
 Error: Failed to create: /usr/local/opt/readline  
 Things that depend on readline will probably not build.  
 ==> Summary  
 /usr/local/Cellar/readline/6.2.4: 31 files, 1.6M, built in 18 seconds  

Anyways, I am digressing and this was becoming too much trouble. So I decided to use a Heroku add-on called clearDB, which turned out to be a great choice. ClearDB was streamlined and works without any issues that I've seen. In order to download ClearDB within my rails app, I run this:

 anthony$ heroku addons:add cleardb:ignite  
 Adding cleardb:ignite on dry-taiga-2649... failed  
  !  Please verify your account to install this add-on  
  !  For more information, see http://devcenter.heroku.com/categories/billing  
  !  Verify now at https://heroku.com/verify  

And get an error, which requires me to go to the Heroku site and update my billing info, which is ok to do because Heroku and ClearDB are free anyways within certain criteria that my app met. You can check these out here. Just scroll down to the database options and click Ignite (the free one). Anyways, so after having done that:

 anthony$ heroku addons:add cleardb:ignite  
 Adding cleardb:ignite on dry-taiga-2649... done, v7 (free)  
 Use `heroku addons:docs cleardb:ignite` to view documentation.  

Looks good. Now I check my heroku database configuration:

 anthony$ heroku config  
 === dry-taiga-2649 Config Vars  
 CLEARDB_DATABASE_URL:    your_database_url_here  
 DATABASE_URL:        your_database_url_here  
 HEROKU_POSTGRESQL_GREEN_URL: you_database_url_here  

and change my configuration to use the new clearDB database:

 anthony$ heroku config:set DATABASE_URL='mysql://bd4b8775c1:642780af@us-cdbr-east-03.cleardb.com/heroku_02a7aa6c930d765?reconnect=true'  
 Setting config vars and restarting dry-taiga-2649... done, v9  
 DATABASE_URL: mysql://:642780af@us-cdbr-east-03.cleardb.com/heroku_02a7aa6c930d765?reconnect=true  

Now, I can try running my app again.

 anthony$ heroku ps:scale web=1  
 Scaling web dynos... done, now running 1  
 anthony$ heroku ps  
 === web (1X): `bundle exec rails server -p $PORT`  
 web.1: crashed 2013/05/29 13:12:26 (~ 4m ago)  

Still not working at all. Figured out at this point that since I'm using mysql2 gem, I needed to change mysql:// to mysql2:// in the heroku config:set command:

 anthony$ heroku config:set DATABASE_URL='mysql2://bd4b87fd3175c1:642780af@us-cdbr-east-03.cleardb.com/heroku_02a7aa6c930d765?reconnect=true'  
 Setting config vars and restarting dry-taiga-2649... done, v10  
 DATABASE_URL: mysql2://bd4b87fd3175c1:642780af@us-cdbr-east-03.cleardb.com/heroku_02a7aa6c930d765?reconnect=true  
 anthony$ heroku ps:scale web=1  
 Scaling web dynos... done, now running 1  
 anthony$ heroku ps  
 === web (1X): `bundle exec rails server -p $PORT`  
 web.1: up 2013/05/29 13:18:29 (~ 50s ago)  

SUCCESS!!! Now I can finally try to open my Heroku app:

 anthony$ heroku open  
 Opening dry-taiga-2649... done  

Awesome! Looks good here, but when I visited my app, it wasn't working. Turns out I had to migrate my database, which didn't work for me:

 anthony$ heroku run rake db:migrate  
 Running `rake db:migrate` attached to terminal... up, run.9906  
 DEPRECATION WARNING: You have Rails 2.3-style plugins in vendor/plugins! Support for these plugins will be removed in Rails 4.0. Move them out and bundle them in your Gemfile, or fold them in to your app as lib/myplugin/* and config/initializers/myplugin.rb. See the release notes for more on this: http://weblog.rubyonrails.org/2012/1/4/rails-3-2-0-rc2-has-been-released. (called from <top (required)> at /app/Rakefile:7)  
 DEPRECATION WARNING: You have Rails 2.3-style plugins in vendor/plugins! Support for these plugins will be removed in Rails 4.0. Move them out and bundle them in your Gemfile, or fold them in to your app as lib/myplugin/* and config/initializers/myplugin.rb. See the release notes for more on this: http://weblog.rubyonrails.org/2012/1/4/rails-3-2-0-rc2-has-been-released. (called from <top (required)> at /app/Rakefile:7)  
 Connecting to database specified by DATABASE_URL  
 Migrating to CreateLabs (20130503083027)  
 Migrating to AddAttachmentDataToLab (20130509050606)  
 == AddAttachmentDataToLab: migrating =========================================  
 -- add_column(:labs, :data_file_name, :string)  
 rake aborted!  
 An error has occurred, all later migrations canceled:  
 Mysql2::Error: Table 'heroku_02a7aa6c930d765.labs' doesn't exist: ALTER TABLE `labs` ADD `data_file_name` varchar(255)/app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:243:in `query'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:243:in `block in execute'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'  
 /app/vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.6/lib/active_support/notifications/instrumenter.rb:20:in `instrument'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:243:in `execute'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/mysql2_adapter.rb:211:in `execute'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:459:in `add_column'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:466:in `block in method_missing'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:438:in `block in say_with_time'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:438:in `say_with_time'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:458:in `method_missing'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:334:in `method_missing'  
 /app/db/migrate/20130509050606_add_attachment_data_to_lab.rb:3:in `up'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:370:in `up'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:410:in `block (2 levels) in migrate'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:410:in `block in migrate'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract/connection_pool.rb:123:in `with_connection'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:389:in `migrate'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:528:in `migrate'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:720:in `block (2 levels) in migrate'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:777:in `call'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:777:in `ddl_transaction'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:719:in `block in migrate'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:700:in `each'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:700:in `migrate'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:570:in `up'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:551:in `migrate'  
 /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.6/lib/active_record/railties/databases.rake:153:in `block (2 levels) in <top (required)>'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/task.rb:246:in `call'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/task.rb:246:in `block in execute'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/task.rb:241:in `each'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/task.rb:241:in `execute'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/task.rb:184:in `block in invoke_with_call_chain'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/task.rb:177:in `invoke_with_call_chain'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/task.rb:170:in `invoke'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/application.rb:143:in `invoke_task'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/application.rb:101:in `block (2 levels) in top_level'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/application.rb:101:in `each'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/application.rb:101:in `block in top_level'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/application.rb:110:in `run_with_threads'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/application.rb:95:in `top_level'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/application.rb:73:in `block in run'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/application.rb:160:in `standard_exception_handling'  
 /app/vendor/bundle/ruby/1.9.1/gems/rake-10.0.4/lib/rake/application.rb:70:in `run'  
 Tasks: TOP => db:migrate  
 (See full trace by running task with --trace)  

This gave me a ton of trouble trying to figure out why this was happening. But in the end here is what worked. I restart the dynos:

 anthony$ heroku restart  
 Restarting dynos... done  

And reset the database:

 anthony$ heroku run rake db:reset  
 Running `rake db:reset` attached to terminal... up, run.1906  
 DEPRECATION WARNING: You have Rails 2.3-style plugins in vendor/plugins! Support for these plugins will be removed in Rails 4.0. Move them out and bundle them in your Gemfile, or fold them in to your app as lib/myplugin/* and config/initializers/myplugin.rb. See the release notes for more on this: http://weblog.rubyonrails.org/2012/1/4/rails-3-2-0-rc2-has-been-released. (called from <top (required)> at /app/Rakefile:7)  
 DEPRECATION WARNING: You have Rails 2.3-style plugins in vendor/plugins! Support for these plugins will be removed in Rails 4.0. Move them out and bundle them in your Gemfile, or fold them in to your app as lib/myplugin/* and config/initializers/myplugin.rb. See the release notes for more on this: http://weblog.rubyonrails.org/2012/1/4/rails-3-2-0-rc2-has-been-released. (called from <top (required)> at /app/Rakefile:7)  
 Connecting to database specified by DATABASE_URL  
 -- create_table("labs", {:force=>true})  
   -> 0.0796s  
 -- initialize_schema_migrations_table()  
   -> 0.0886s  
 -- assume_migrated_upto_version(20130510011111, ["/app/db/migrate"])  
   -> 0.0285s  

Since we are in production, the app might have been holding on to a past schema. It turns out that this was the issue. I had some mistakes in my migrations, and once I fixed all those, I had to reset the database and get rid of the old schema.rb file, which was holding on to the past database settings. Once I reset the database and migrate the database again...

 anthony$ heroku run rake db:migrate  
 Running `rake db:migrate` attached to terminal... up, run.5697  
 DEPRECATION WARNING: You have Rails 2.3-style plugins in vendor/plugins! Support for these plugins will be removed in Rails 4.0. Move them out and bundle them in your Gemfile, or fold them in to your app as lib/myplugin/* and config/initializers/myplugin.rb. See the release notes for more on this: http://weblog.rubyonrails.org/2012/1/4/rails-3-2-0-rc2-has-been-released. (called from <top (required)> at /app/Rakefile:7)  
 DEPRECATION WARNING: You have Rails 2.3-style plugins in vendor/plugins! Support for these plugins will be removed in Rails 4.0. Move them out and bundle them in your Gemfile, or fold them in to your app as lib/myplugin/* and config/initializers/myplugin.rb. See the release notes for more on this: http://weblog.rubyonrails.org/2012/1/4/rails-3-2-0-rc2-has-been-released. (called from <top (required)> at /app/Rakefile:7)  
 Connecting to database specified by DATABASE_URL  
 Migrating to CreateLabs (20130503083027)  
 Migrating to AddAttachmentDataToLab (20130509050606)  
 Migrating to AddLatLongToLab (20130510011111)  

Successful! Now at this point, I have fully deployed with Heroku, and can visit my page. Now to hook it up with Amazon AWS S3. Start with creating an Amazon AWS account. Once you've done that, you can go into the My Account/Console -> Security Credentials. Under Access Keys, you can create a new Access Key. Once you have that, you can set your Heroku App up with your Amazon Access Keys:

 anthony$ heroku config:set AWS_ACCESS_KEY_ID=your_key_here AWS_SECRET_ACCESS_KEY=your_key_here  
 Setting config vars and restarting dry-taiga-2649... done, v14  
 AWS_ACCESS_KEY_ID:   your_key_here  
 AWS_SECRET_ACCESS_KEY: your_key_here  

Once this is done, in your Amazon AWS webpage navigate to the Service tab on the top left -> Storage and Content Delivery -> S3. Now you can create a bucket on Amazon S3. A "bucket" is S3's root folder basically, and the name you give it has to be unique across all S3 buckets. Once this bucket is created, you can then set the configuration of your heroku app to the bucket:

 anthony$ heroku config:set S3_BUCKET_NAME=your_bucket_name  
 Setting config vars and restarting dry-taiga-2649... done, v15  
 S3_BUCKET_NAME: your_bucket_name  

Next, you add 'gem aws-sdk' to gemfile. Delete your Gemfile.lock, and run bundle install. Remember, we have to regenerate a new Gemfile.lock file because we made changes to the gemfile. Then, within your app you must add this code to your production.rb file to let it work with S3.

 # config/environments/production.rb  
 config.paperclip_defaults = {  
  :storage => :s3,  
  :s3_credentials => {  
   :bucket => ENV['AWS_BUCKET'],  
   :access_key_id => ENV['AWS_ACCESS_KEY_ID'],  
   :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']  
  }  
 }  

And also, do a bit more configuration for your Heroku app in terminal:

 $ heroku config:set AWS_BUCKET=your_bucket_name  
 $ heroku config:set AWS_ACCESS_KEY_ID=your_access_key_id  
 $ heroku config:set AWS_SECRET_ACCESS_KEY=your_secret_access_key  

Almost there. Check any changes you've made to your code that you haven't committed yet, and then commit and push your code first to your master branch, then push to your Heroku branch. And once this is all done, restart your Heroku app with:

 anthony$ Heroku restart  

Run your dyno, check your dyno status, and check your app! You should now be able to see your app in production, upload through Heroku, and go to your AWS S3 management console and see your files uploaded to the Amazon cloud server! And best of all, with a small enough app this should all be free of any charges. Here are the resources I used along the way:

Quick start deploy with Heroku
Detailed start and deploy on Rails 3 with Heroku
How to set up Paperclip and S3 with Heroku

Hope this helps some of you out there. I check my email extremely frequently, and I'd love to help any of you out if you have questions. Simply comment below!