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


  • How to filter model data before rendering in Streamlined

    One question that seems to come up a lot on the Streamlined mailing list is how best to filter the records that are displayed in the list view using a certain set of conditions. There are several ways of doing this, but the simplest way is to use Rails’ built-in scoping methods in conjunction with an around filter.

    For example, say we have a Task model and a TaskController that is Streamlined-enabled. The TasksController will display a list of all Tasks in the system by default. What if we only want to display Tasks for the currently logged-in user? Something like this would work:

    around_filter :scope_by_user, :only => [:list, :index]
    
    def scope_by_user
      Task.find_with_user_scope(current_user) { yield }
    end
    

    Once this code is added to the TaskController, any calls to Task#find within the associated actions, views, and helpers will be scoped. Only tasks belonging to the current user will be listed.

    What if we still want to perform an unscoped Task#find within an action? We can eliminate the scoping for a specific block of code using the #with_exclusive_scope method. It looks like this:

    Task.with_exclusive_scope { code_that_should_not_be_scoped }
    

    And that, folks, is how easy it is to filter lists in Streamlined.

  • Is Communism really dead?

    I found Misreading the Tea Leaves by J.R. Nyquist to be pretty thought-provoking. Maybe you will too.

  • raleigh.rb has a podcast

    Did you realize that Raleigh’s own Ruby Brigade now has a podcast? Yes ladies and gents, it’s true.

    I’ve been recording the last few meetups on my MacBook. The audio quality isn’t half bad. I hope to expand the podcast in the future with non-meetup content. For now, it can serve as a good way to catch up if you’re out of town or otherwise can’t make it to our regular monthly meeting.

  • Using named routes in Streamlined addition files

    For you Streamlined users out there, here’s an easy way to include named routes in your Streamlined addition modules. Previously, you had to hard code the URLs like so:

    module OrderAdditions
      def name_link
        link_to user.name, "/users/show/#{user.id}"
      end
    end
    
    Order.class_eval do
      include OrderAdditions
      include ActionView::Helpers::UrlHelper
      include ActionView::Helpers::TagHelper
    end
    
    Streamlined.ui_for(Order) do
      list_columns :name_link
    end
    

    By including Rails 2’s new ActionController::UrlWriter module, you can access any named or RESTful routes you’ve defined in routes.rb:

    module OrderAdditions
      def name_link
        link_to user.name, user_url(user.id)
      end
    end
    
    Order.class_eval do
      ...
      include ActionController::UrlWriter
      default_url_options[:host] = APP_HOST
    end
    

    It would be nice for this to get baked into Streamlined somehow so UrlWriter automatically gets included, but until that happens this is a good way to get rid of those pesky hard-coded URLs.