TL;DR
I’m trying to dynamically generate an asset URL using HTML5 data elements, on the client-side. This means the asset name isn’t available until runtime in the browser, which prevents ERB from pre-processing on the server.
Is there a work-around or best practice for handling such a situation?
Background
I’m using the Fusion Charts charting plugin in a Rails application, which uses various SWF files to generate charts. I’m in the process of upgrading the application to Rails 3.1 and have placed these SWF files into /vendor/assets/javascripts/fusion_charts.
Within the application, I dynamically specify the type of chart to draw using HTML5 data attributes, like so:
<%# ... metric.html.erb ... %>
<div id='chart-container' class='fusion-chart'
data-chart-type='MSLine'
data-source-url="<%= @metric.data_url %>">
Then I have a simple jQuery plugin written in CoffeeScript that pulls these data attributes and wires things to Fusion Charts:
// ... charting_plugin.js.coffee ...
chart = new FusionCharts
swfUrl: "/assets/fusion_charts/#{data.chartType}.swf"
chart.setJSONUrl data.sourceUrl
chart.render containerId
The problem I’m running into is the swfUrl argument. To follow the guidance offered in the RoR Asset Pipeline guide, I should use the asset_path helper in ERB, but this won’t work because data.chartType is bound on the client, at run-time, and can’t be pre-processed server-side.
<# ... charting_plugin.js.coffee.erb: This won't work; data.chartType isn't defined ... %>
chart = new FusionCharts
swfUrl: "<%= asset_path "fusion_charts/#{data.chartType}.swf" %>"
chart.setJSONUrl data.sourceUrl
chart.render containerId
Work Arounds
The simplest work-around (the one I’m using currently) is to simply move the SWF files back into /public/fusion_charts and not worry about the asset fingerprinting complexity of the pipeline. That said, I’m new to the pipeline, so maybe I’m missing something obvious.
Is there a better way to handle client-side asset URLs like this?
One solution would be to have a lookup table for swf files by chart type, eg:
Then add a function to get the correct path on the client side at runtime like so:
Then change your setup call to be:
IE, use ERB to build a list of all possible paths you’ll need at asset compilation time, and then do a lookup at run time on the client. (and of course you’ll need to coffee script-ize the above – I’m not a coffee guy, I prefer latte’s. 🙂