• 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.


  • The 5th of November

    This seems like a very good idea.

  • Where is the logic in this?

    There are few things I hate worse then trying to call a business, getting put on hold, and then having to listen to ads for that business while I’m on hold. A happy customer I am not.

  • Use helpers in your Rails PDF templates

    The Rails PDF plugin is a dandy little thing. It wraps the PDF::Writer library for Ruby, allowing PDF templates to be defined like any other Rails view (with a .rpdf extension, of course).

    One thing it doesn’t do is allow access to the parent controller’s helper from within a PDF template. It’s easy enough to patch the plugin to accomplish this, though.

    First, open up vendor/plugins/railspdf/lib/railspdf.rb and take a gander. This is the section we’re interested in:

    ...
    class PDFRender < ActionView::Base
      def initialize(action_view)
        @action_view = action_view
      end
      ...
    

    PDF templates get rendered in the context of this class. All we need to do to gain access to the controller's helper here is include the helper from inside the class initializer, like so:

    ...
    class PDFRender < ActionView::Base
      def initialize(action_view)
        @action_view = action_view
        prefix = action_view.controller.class.to_s.gsub(/Controller/, '')
        self.class.send(:include, "#{prefix}Helper".constantize)
      end
      ...
    

    We first calculate the prefix of the helper based on the class of the controller assigned to the view. Then we include the helper in the current class by constantizing the resulting string.

    We're almost done. Since ApplicationHelper should be available to every controller and helper in the system, let's include it here for good measure:

    ...
    class PDFRender < ActionView::Base
      include ApplicationHelper
      
      def initialize(action_view)
        @action_view = action_view
        prefix = action_view.controller.class.to_s.gsub(/Controller/, '')
        self.class.send(:include, "#{prefix}Helper".constantize)
      end
      ...
    

    And we're done! Piece of cake. Now we can reference methods from inside our controller's helper. We can, of course, modify this hack somewhat so that the same helper (something like "PdfHelper" maybe) is included for all of our templates. This enables us to isolate our PDF-specific helper methods in a single module.

    And before you ask, yes, it's nasty to be modifying the plugin directly. There is a way to inject this patch into the PDFRender class without touching anything in the plugin... but I've gotta leave something for you to figure out! :)

  • Hey, flexmock and unit_record, play nice!

    So you’re savvy with flexmock, a fine Rails plugin that lets you create mock objects in your tests. You’ve been coding up a boatload of fine tests that are elegant in their isolation thanks to your super mocks. They all run fine, but they’re kind of slow so you go Googling for techniques to speed them up.

    You stumble across a wonderful plugin called unit_record that can dramatically speed up your unit tests by disconnecting them from the database. You install it, run your tests, and wham, you get a barrage of error messages like this:

    ActiveRecord is disconnected; database access is unavailable in unit tests.
    

    There could be one or two things going on here. The first possibility is that one or more of your unit tests are still attempting to access the database via a finder or a fixture. This is the most likely case if you’re only getting a few errors. If you’re getting an error for every single unit test in your suite, though, then something else is going on: flexmock is not playing nicely with unit_record.

    The root of the problem is that unit_record attempts to turn off transactional fixtures for your unit tests when you run them, but flexmock hijacks unit_record by defining its own alias chains for setup/teardown.

    I got around this problem by updating my unit_test_helper.rb file to include the following:

    class Test::Unit::TestCase
      self.use_transactional_fixtures = false
    end
    

    It’s unfortunate this has to be done, but it’s a better option than digging into the flexmock plugin itself… especially if you plan on upgrading to a new version of flexmock anytime soon. Don’t forget that you should be disconnecting ActiveRecord in your unit_test_helper.rb as well. This is what my entire file looks like:

    require File.dirname(__FILE__) + '/../test_helper'
    
    require 'unit_record'
    ActiveRecord::Base.disconnect!
    
    class Test::Unit::TestCase
      # Unit_record is trying to do this for us, but since we're
      # using flexmock's test case it patches the wrong class.
      self.use_transactional_fixtures = false
    end
    

    Hope this helps someone who was as equally stumped as I was. Happy testing!

    Update on 12/1/07: After chatting with Jim Weirich (the creator of flexmock) and doing some more tweaking, it became obvious that the problem is not with flexmock but lies somewhere else. I removed all references to flexmock from my code and still had trouble. The transactional fixture switch seems to be getting set between test runs, but I can’t locate where it’s happening. If anyone else finds a solution to this problem, please let us know by posting a comment here.