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


  • Fantastic Foxmarks

    Foxmarks LogoHave you wondered how to effectively synch bookmarks between work and home? I discovered the Foxmarks plugin for Firefox almost by accident last week and it does the trick for me. Better still, it’s fast and lightweight, the perfect companion for an agile developer.

    Foxmarks installs into Firefox in seconds. Once running, all we need to do is hit Command-Shift-S to synch our bookmarks with a remote server. Hop on to a second system, install the plugin again, and hit Command-Shift-S to download the bookmarks we just synched. End of story? Not quite. What if we add a different bookmark on both computers at the same time? Foxmarks is smart enough to handle merging both bookmarks the next time we synch.

    Foxmarks is a really wonderful tool and I highly recommend it. I no longer have to worry about my bookmarks getting out of synch between the computers that I work on. This has saved me a lot of time and angst.

  • Agile RTP: A new user group in Raleigh

    Agile RTP is a new user group started in the Raleigh area by Jared Richardson. The first meeting will be on March 22nd where we’ll be video conferencing with the agile group in Charlotte to hear Dr. Laurie Williams speak about test-driven development. I was actually considering driving to Charlotte for this speech, so when Jared told me we’d be able to enjoy it right here in Raleigh I was totally psyched. Get more details on the event and don’t forget to mark your calendar.

  • Overriding existing Rake tasks

    I added some long-running integration tests to a Rails application today and quickly began getting irritated that issuing the rake command runs all tests… unit, functional, AND integration. Since I run rake quite frequently, any sizable delay can quickly get annoying.

    The task that gets executed by rake is the :test task. After spending a few minutes trying to replace it, I discovered that there isn’t an immediately obvious way to override an existing task in Rake. After jumping through a few hoops, though, I did manage to do it.

    First, here’s my replacement for the existing :test task:

    task :test do
      Rake::Task["test:units"].invoke rescue got_error = true
      Rake::Task["test:functionals"].invoke rescue got_error = true
      raise "Test failures" if got_error
    end
    

    All it does is run the unit and functional tests, but no integration tests. I stuck this in my Rakefile right after the require 'tasks/rails' line. Next up, I reopened the Rake::TaskManager module to create my own little helper method to remove a task:

    Rake::TaskManager.class_eval do
      def remove_task(task_name)
        @tasks.delete(task_name.to_s)
      end
    end
    

    Lastly, I called this method from another method defined inside my Rakefile. This way, I could use syntax like remove_task :test which would fit with my other task definitions in the file. This is how everything looks put together (remember that this code should be inserted immediately after the require 'tasks/rails' line or it won’t work):

    Rake::TaskManager.class_eval do
      def remove_task(task_name)
        @tasks.delete(task_name.to_s)
      end
    end
    
    def remove_task(task_name)
      Rake.application.remove_task(task_name)
    end
    
    # Override existing test task to prevent integrations
    # from being run unless specifically asked for
    remove_task :test
    task :test do
      Rake::Task["test:units"].invoke rescue got_error = true
      Rake::Task["test:functionals"].invoke rescue got_error = true
      raise "Test failures" if got_error
    end
    

    This did the trick for me, but it’s kind of long. Anyone know a better way of doing it?

  • Selecting matching key/value pairs from a hash

    I ran into a situation today where I needed to pull out all key/value pairs from a hash that matched the keys in a pre-existing array. This is what I initially came up with:

    hash = { :foo => "foo", :bar => "bar", :bat => "bat" }
    hash.symbolize_keys.reject { |k, v| ![:foo, :bar].include?(k) }
    
    >>> returns { :foo => "foo", :bar => "bar" }
    

    Kind of ugly, ain’t it? I sure don’t want to repeat those lines elsewhere. Let’s see if we can do better:

    class Hash
      def select_all(*attrs)
        symbolize_keys.reject { |k, v| !attrs.include?(k) }
      end
    end
    
    { :foo => "foo", :bar => "bar", :bat => "bat" }.select_all(:foo, :bar)
    
    >>> returns { :foo => "foo", :bar => "bar" }
    

    Now that’s more like it. Extending Hash lets me call a method directly on my hash. I can also use this method anywhere in my Rails application if I place the Hash code in lib/hash.rb and require 'hash' from my environment.rb file. Isn’t Ruby beautiful?

    Anyone else have a better way of doing this? I’m open to suggestions.