• CORS woes on Heroku

    ,

    After spending the past 4 hours attempting to solve what boiled down to a rather simple problem, I figure I’d better blog about it to save someone else the time and effort.

    If you’ve been leveraging Passenger’s new –nginx-config-template command line option to add CORS headers to static assets served from a Rails app hosted on Heroku, and the CORS headers recently disappeared under mysterious circumstances… read on.

    I’ve been using the method described here to add CORS headers to custom fonts served from a Heroku-hosted Rails app that’s proxied by Nginx which handles serving static files. I recently updated to Rails 4.2.2 and suddenly, my custom fonts (.woff and .woff2 files) no longer had CORS headers on them.

    After the aforementioned hours spent scratching my head, I discovered that the latest version of the sprockets gem is generating asset digests that are 64 chars in length, where previously they had been 32. Nginx’s default regexp for identifying requests for static assets assumes the digest will be 32 chars long, like so:

    # Rails asset pipeline support.
    location ~ "^/assets/.+-[0-9a-f]{32}\..+" {
      error_page 490 = @static_asset;
      error_page 491 = @dynamic_request;
      recursive_error_pages on;</code>
    
      if (-f $request_filename) {
        return 490;
      }
      if (!-f $request_filename) {
        return 491;
      }
    }
    

    Changing the regexp to recognize digests that are 64 chars in length immediately solved the problem:

    location ~ "^/assets/.+-[0-9a-f]{64}\..+" {
       ...
    }
    

    I had to laugh after something so stupid and silly cost me a good chunk of my Saturday to debug. But at least it’s working now. My statically served custom fonts have the correct CORS headers and Chrome and Firefox are happy again.


Need help?

I’m an independent software developer available for consulting, contract work, or training. Contact me if you’re interested.


  • Validation assertion added to test_spec_on_rails

    I’ve added a new assertion to test_spec_on_rails that enables verification that validates_presence_of is being called correctly on your ActiveRecord models. For example, say you have a model like this:

    class User < ActiveRecord::Base
      validates_presence_of :first_name, :last_name
    end
    

    You would typically test this validation by leaving a field blank, calling valid? or save on the instance, and checking the errors collection for messages:

    describe "User" do
      it "should validate presence of first name" do
        user = User.new(:first_name => nil)
        user.valid?
        user.errors.on(:first_name).should == "can't be blank"
      end
    end
    

    Aside from being tedious to write, this method of testing isn't very fast. With the latest version of test_spec_on_rails your test becomes:

    describe "User" do
      it_should_validate_presence_of :first_name, :last_name
    end
    

    Nice, simple... and fast. Behind the scenes, validation reflection is being used to ensure that validates_presence_of is being called on the model class. The model itself is never instantiated which speeds things up. The test itself is also very clean and easy to read. (You can't get much cleaner than a single line of code, right?)

    What about verifying options that are passed to the validation? This new enhancement handles that too:

    class User < ActiveRecord::Base
      validates_presence_of :ssn, :if => :ssn_required?
    end
    
    describe "User" do
      it_should_validate_presence_of :ssn, :if => :ssn_required?
    end
    

    If the options passed to the assertion aren't used on the actual validation then the test will fail.

    Ready to start rolling with this new hotness? test_spec_on_rails is now on Git so unless you're running Edge Rails you can't use script/install to grab it. My suggestion is to clone from Git into vendor/plugins and then svn:ignore the .git file:

    git clone git://github.com/pelargir/test_spec_on_rails.git vendor/plugins/test_spec_on_rails
    svn propset svn:ignore .git vendor/plugins/test_spec_on_rails
    
  • Why does tabbing skip certain form fields in OS X?

    Isn’t it incredibly annoying how both Firefox and Safari skip select fields and check boxes while keyboard tabbing through a form? Fortunately, there is an incredibly simple solution. (The fact that this isn’t a default setting in OS X makes me wonder if the Apple people wrote that particular preference pane on a Friday.)

  • Contra dancing

    I went contra dancing with some friends last Friday. I’ve done English country dancing before, but never contra. It’s quite a workout, but really fun. Our friends were kind enough to post this video from the event:

  • Building arrays of similar objects in Ruby

    I often find myself having to build arrays of similar objects in my tests. For example:

    def create_user
      :some_user
    end
    
    users = [create_user, create_user, create_user]
    

    It seems wasteful to repeat the same method call three times. One solution is to use the #times method to append to an array, like this:

    users = []
    3.times { users << create_user }
    

    This just doesn't seem very elegant, though. It feels like I should be able to collect the results from each method call with a single line of code. I experimented with the multiplication operator to see if it might be able to do what I wanted, but didn't get far.

    Here's one possible solution I came up with:

    class Integer
      def of
        result = []
        times { result << yield }
        result
      end
    end
    
    users = 3.of { create_user }
    # returns [:some_user, :some_user, :some_user]
    

    The #of method can now be called on an integer. It uses #times to call the given block three times and appends the result to an array which is then returned. Much more elegant. Another way to achieve this on a single line is:

    users = (0..2).to_a.collect { create_user }
    

    This doesn't feel as nice to me. It's visually complex and, at first glance, the zero-basing of the range hides the fact that we're collecting three items, not two. The benefit is that no reopening of the Integer class is required.

    How would you solve this problem?