The Secret to Referencing Middleman's `asset_hash`-ed Assets
But I've got the key to it here to share with you, fellow wayward code traveler.
It's all about source paths
Whether you need to reference the asset in a blog post or in a helper somewhere, you must make use of Middleman's source path to the asset.
For example, if my blog is at "/blog"
, and my article is named something like: "2014-09-17-zurb-s-foundation-why-it-s-time-to-switch.html.markdown"
(generated by middleman article
), the source path to my article is: "/blog/2014-09-17-zurb-s-foundation-why-it-s-time-to-switch/index.html"
(if using activate :directory_indexes
) or "/blog/2014-09-17-zurb-s-foundation-why-it-s-time-to-switch.html"
if not.
In either case, when using article subdirectories for assets, there is a folder: "/blog/2014-09-17-zurb-s-foundation-why-it-s-time-to-switch/"
which contains my assets.
Now remember, when I say folder, for now, we are only talking about source paths: the paths Middleman makes use of prior to building final output paths, under your /source
directory. The paths you develop against before running middleman build
. The main difference between source paths and output paths is that the date gets converted from dashes to slashes in output paths: from "/blog/2014-09-17-zurb-s-foundation-why-it-s-time-to-switch"
to "/blog/2014/09/17/zurb-s-foundation-why-it-s-time-to-switch"
. Of course, other wild stuff can happen with output paths depending on plugins you're using, etc.
We good so far? Good. Now we've got our source path folder for the article's assets: "/blog/2014-09-17-zurb-s-foundation-why-it-s-time-to-switch/"
. What we want to do from here is, in our "2014-09-17-zurb-s-foundation-why-it-s-time-to-switch.html.markdown"
file, refer to the asset in question like so:
![My Image](/blog/2014-09-17-zurb-s-foundation-why-it-s-time-to-switch/uber_nav.png 'My Image')
Note that we are using the correct source path to the article subdirectory, "/blog/2014-09-17-zurb-s-foundation-why-it-s-time-to-switch/"
, and then appending the actual image to it ("uber_nav.png"
). When we do the above, Middleman generates an image_tag
for this source path. The image_tag
helper in Middleman is implemented using Middleman's own url_for
, which is responsible for converting these source paths into output paths.
In this case you will find the output path, assigned as the value for the src
attribute to the <img>
tag, to be something like "/blog/2014/09/17/zurb-s-foundation-why-it-s-time-to-switch/uber_nav-12323.png"
if it worked (or simply "uber_nav-12323.png"
if you're using relative paths). Glorious! How relieved I was when that worked!
I need attributes and stuff
Things get slightly more complicated if you want to add additional attributes to your image that the markdown image syntax can't handle.
First, you need to append .erb to the filename, like so: "2014-09-17-zurb-s-foundation-why-it-s-time-to-switch.html.markdown.erb"
. Once you've done that you can go ahead and convert the above image markdown syntax into something like this:
<%= image_tag '/blog/2014-09-17-zurb-s-foundation-why-it-s-time-to-switch/uber_nav.png', class: 'something cool', width: '50%' %>
Remember, this will take the source path above and call url_for
with it, getting you the asset_hash
-ed image. Nice!
A note on referencing asset_hash-ed assets properly within custom helpers
If you've got some custom helper code like I did that generates asset paths for you, remember the above concepts. You need to first get the source path to the asset, and then you can call url_for(source_path_to_asset)
, just like Middleman does internally, to get the asset with its hashed filename.
Disable activate :cache_buster
!
Do that, because I've heard these conflict with one another. They are two different ways of handling caching, with cache_buster
appending a query param instead of rewriting the filename like asset_hash
does.