Tuesday, July 17, 2012

Scale worker processes in Heroku for Sinatra with Delayed Job

I've done this a few times for some of my personal projects and it works pretty well. Every single time I do it I always have the same problems so here is a checklist to keep you from going off the rails (HAHAHA!).
  • Make sure you've got the right gems: delayed_job, delayed_job_active_record, workless, heroku
  • Make sure you've configured delayed job to use your workless process scaler, and your scaler matches the heroku stack you are running
  • Create a Procfile with your worker definition (see gist above)
  • Set all required environment variables: APP_NAME, HEROKU_PASSWORD, HEROKU_USER
  • I usually use the heroku scheduler app add-on to run my rake task that adds stuff to my jobs table.
I've seen the following HTTP errors when running misconfigured apps:  
  • 404.  This is what you'll get if you are missing the APP_NAME because  if you look at the ps_scale method in the heroku gem, it is using that name to build a URL so without it your URL will be broken.
  • 401. This is what you'll get if you forget to set the username and password environment variables because the ps_scale method of the heroku api requires authentication.
  • 422 (Unprocessable Entity). This is what you'll get if you forget the procfile.  It is a shitty error message that is trying to tell you that heroku doesn't know how to create a worker process if you don't define it. Ick.
Allright.  Best of luck future me, and whoever else finds this useful.

Monday, May 28, 2012

Sinatra-san, meet kaminari

Here is a gist with a few snippets that I used to get kaminari pagination working with sinatra. Sinatra is already big in Japan so it's super easy! I ran out of steam trying to override the kaminari templates. My guess is that you'd have to modify kaminari a bit to make that happen. Leave a note in the comments if you figure that out.

Friday, March 30, 2012

HTTP Accept headers for PhoneGap and Rails

Building a PhoneGap mobile application with a Rails backend? You should know about HTTP Accept headers and Rails. The important thing to understand is that best practice in Rails is NOT to use the Accept headers. There is a nice writeup here that explains why in glorious detail. Summary: browser implementation of HTTP Accept headers is broken. Rails best practice is to set the :format parameter in the request. However, if you like the accept headers they are supported but the rules around what is a valid accept header in rails can be tricky. For example: if your accept header matches the following regex:

BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/


Then rails throws it away and defaults to text/html mime type. I know, right? We had a problem with backbone and JQuery. Our application was sending the following accept headers:
application/json, text/javascript, */*; q=0.01
Looking at that you would expect that because we ask for a json response we should get one. Rails returns text/html in this case because our accept headers looks like the kind of thing the browser would send along, thus broken and unreliable. You might be thinking: hey, every other rails app I've built hasn't had this problem. Well, the reason most people don't have this problem is that rails "fixes" the default jquery behavior in the rails jquery-ujs gem. They set a ajaxSetup beforeSend callback in JQuery that puts the */* at the beginning of the header, which is what the magic rails regex wants to see. Here is how I fixed my accept header in JQuery.


$(function() {
$.ajaxSetup({
'beforeSend': function(xhr) {
xhr.setRequestHeader("accept", "appplication/json");
}
});
});

Friday, March 23, 2012

Creating a new Rails app Segmentation Fault on Ruby 1.9.3

Ran across this one today. I was trying to create a new rails app on Ruby 1.9.3.


/Users/oldjosh/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/net/http.rb:799: [BUG] Segmentation fault
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.2.0]


It turns out that if you don't compile 1.9.3 against openSSL from macports or some other non-apple source, you end up with a ruby that segfaults when it tries to do ssl. Thus bundler fails to fetch gems when you create a rails app. My fix was to reinstall 1.9.3 and specify where my macports openssl installation was.


$ rvm reinstall 1.9.3 --with-openssl-dir=/opt/local


RVM has another option to get around this if you don't have macports or some other alternative. See their docs for more info. And see the bug that helped me solve my problem.

Wednesday, March 21, 2012

Vimeo's White Screen of Death in IE

Recently I noticed my embedded Vimeo players were all broken in IE. I was getting just a blank white screen. It turns out Vimeo requires you to have Flash version >= 10. That is fine, but unfortunately their player doesn't fail gracefully if you have an older flash version. My VM had Flash 6. It is simple to check for a particular version of flash in JS. That allows us to fail gracefully on behalf of Vimeo. Here is a snippet that can check if the client browser is good enough for vimeo.


<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<script>
function goodEnufForVimeo(){
var playerVersion = swfobject.getFlashPlayerVersion();
return (playerVersion.major >= 10);
}
</script>

Monday, December 5, 2011

Tips for First Time Braintree Integrators

I just finished building CollegeSet. A web application for helping students pay for college (It's nonprofit. It's fun. go make a donation!). We use Braintree Payments for our gateway. I had a great experience building against their API and I'll definitely use them again! Here are a few tips to anyone else who is just starting to integrate with Braintree.

Read the examples


Their github profile has sample applications in many different languages. Don't start yours without spending some serious time with theirs!

TDD it


This part of your application is too important not to test. Unfortunately, it is one of the more difficult parts to test. I found that a good mocking library was enough to let me test most of the controller logic around my payments. I fell short of doing end to end testing like this person describes.

Give yourself time


It took us 3 weeks to get our application approved for use with Braintree. (The holdup wasn't Braintree.) They audit your site and require the terms of service, so we ended up waiting for lawyers and clients to hash out those details before we could get approval. You do get instant access to their sandbox though, which means you can do development in parallel with the approval process. Don't wait until the last minute!

Room for Improvement


Overall Braintree was the best of all the solutions I researched. Their "transparent redirect" helps you minimize your PCI compliance exposure while maintaining a great user experience (no IFrame), and their API's are great. Of course nobody's perfect... Here is my wishlist for three things that I would like to see from Braintree in the future.

  • A braintree test-proxy gem for easier integration testing.

  • Sample controller and integration tests in the sample applications.

  • A developer console in the sandbox for examining requests and responses.



Edit: ThoughtBot has created Fake Braintree as a way to do braintree integration testing. I'm going to give it a shot.

Saturday, November 12, 2011

Renaming Attributes the Sneaky Way

The names of your models and their attributes are profoundly important to a Rails application. They become the namesakes to everything else: controllers, views, routes, tests. Users of your application are going to see these names in urls, form fields and validation messages. A few minutes early on can save you hours of find/replace, file renames and broken tests down the road. Sometimes you don't have the luxury of a rename. The shortcut is localization! Let's say your application has a User model with an attribute 'sex'. Those 'Sex can't be blank' validation messages are causing your users existential crises. Let's rename sex to gender. Edit en.yml and add the following:


en:
activerecord:
attributes:
user:
sex: Gender


All your validation and form fields are magically renamed. Voila!