Search code examples
rubysinatrahaml

Layout paths not working in Sinatra


Using Sinatra for the web framework and HAML for the pages, I have a layout file at /views/layout.haml. I also have javascript and css files in /public. Within the layout scripts and css are defined similar to this:

%script{:type => "text/javascript", :src => "test.js"}
%link{:rel => "stylesheet", :type => "text/css", :href => "test.css"}

When I have a basic route defined in Sinatra everything works fine:

get '/' do
  haml :index
end

But when the route has multiple parts, such as '/route/1', suddenly the paths to test.js and test.css no longer work. The haml file loads properly, but the paths in the layout are no longer valid.

After experimenting some, if I change the paths to something like "//public/test.js", instead of just "test.js", it again loads... but only for the route /route/1. Unfortunately the first route / no longer loads.

How is this typically handled in Sinatra with routes like this?


Solution

  • You just need to make sure your urls are absolute.

    With :src => "test.js", the browser will make a request relative to the current url. So for the root, /, the request will be for /test.js and will work, but when the current page is /route/1 the request will go to /route/test.js and will fail.

    The direct fix is to just add / to the url, to make the path absolute:

    %script{:type => "text/javascript", :src => "/test.js"}
    

    A more robust solution would be to use the url helper:

    %script{:type => "text/javascript", :src => url("/test.js")}
    

    This will ensure your app will work even if it is mounted somewhere other than the root of you webserver.