Accessing asset-hashed assets with Middleman

If you’re running a blog using Middleman, attempting to use asset_hash in conjunction with Article Subdirectories, you’re gonna have a bad time.

The key to getting this to work is to use the source of the asset when and referencing it using the built in helper methods. This allows Middleman to find the original, but generate a link to the built version including the hash.

TLDR Use current_page.eponymous_directory_path instead of current_page.url.

Example

Let’s say you have a blog post entitled middleman and asset hashing wat. Your project might look something like this:

1
2
3
4
5
6
7
8
9
10
11
- source
  - blog
    - 2016-10-01-middleman-and-asset-hashing-wat.html.markdown.erb
    - 2016-10-01-middleman-and-asset-hashing-wat/wat.jpg
  - build
    - 2016
      - 10
        - 01
          - middleman-and-asset-hashing-wat
            - index.html
            - wat-03d27653.jpg

As the hash is in flux, we don’t want to hard-code it into our post markup. Instead we just want to tell Middleman what image we want to show, and let it handle the rest.

From reading the documentation for directory_indexes, you may come away with the impression that the way to do this is to reference current_page.url, and then the name of the image. Sadly this does not work in production as we end up with a url without a hash:

1
2
![WAT](<%= current_page.url %>wat.jpg)
# <img src="/2016/10/01/middleman-and-asset-hashing-wat/wat.jpg">

In order to fix this we need to reference the source of the asset, not the built version:

1
2
![WAT](/blog/2016-10-01-middleman-and-asset-hashing-wat/wat.jpg)
# <img src="/2016/10/01/middleman-and-asset-hashing-wat/wat-03d27653.jpg">

The fix

The above is kind of verbose, and ideally we don’t want to have to write this out for every image in every post. Instead we can make use of #eponymous_directory_path for this. This method will return the path for a resource, if it were a directory instead of a file.

1
2
![WAT](<%= current_page.eponymous_directory_path %>wat.jpg)
# <img src="/2016/10/01/middleman-and-asset-hashing-wat/wat-03d27653.jpg">

Or as we’re using erb here, we can just drop the markdown and make use of image_tag:

1
<%= image_tag "#{current_page.eponymous_directory_path}wat.jpg" %>

And with that, you should be able to view your image both locally and from its asset–hash’d source in production. 🎉