Tuesday 30 September 2014

Passing raw array variables from Rails to JS to HTML

I was working on highcharts to follow my previous blogpost, and I got the chart to work. That's great, but highcharts is incredibly flexible and has a lot of features one can use to create dynamic and interesting charts.

But to actually get there, I need some data beyond static example data of John and Jane eating fruits. So, I worked on passing PSQL database objects into the AJAX file in Rails, so that I could apply the variables I want into the chart. How and why would someone do this? It's fairly obvious why, but an example would illustrate things a bit better.

The chart is merely an example; there's many situations where one would want to transfer a database item, or value, or anything into their AJAX file, but that's moving things from Ruby to ERB to JS to HTML. The core issue to keep in mind is to keep the object being passed around readable all the way.

In this case, we'll make a chart that depicts a census of people with different jobs in different countries. In this fantasy fiction world, we'll call them ethercrafts to describe how they cast their magic spells in their day to day. There are 2 countries in this example, Zahnheim and Rogalia. The end result is to look like this:



There's 5 different ethercrafts in the chart: Soulreaving, Enforcing, Invoking, Evoking and Empty. The bar graph (admittedly, not the best chart type to describe population, but it'll suit this blogpost) will compare the two countries' populations for each type of ethercraft.

For this post, we'll focus on the X-Axis descriptors, the ethercrafts. Currently, it describes those by the following code in the Highcharts javascript in the ajax file:



Going down the script:

The first variable, ethercrafts is a list of the ethercrafts as strings in an array which will be the xAxis categories, (we'll talk about this further down). Next is an array to describe the countries that will be the series in the graph. Each country is listed, along with the population of people with a certain ethercraft described in magic constant numbers. We don't want magic numbers, but for the time being, those will work for this example - country population variables will come next time as I make progress on highcharts.

Next variable is the options that we'll pass into the chart we want to make. Highcharts lets you name this anything you want, as this variable will just contain a lot of data which will be passed in as an argument for the Chart function which expects its options. The options include where it's being rendered to (in this case, an HTML object with the ID 'container') and the type of chart, which is bar, the title of the chart, what the categories in the xAxis is (which is our ethercrafts variable, where it expects an array), and the yAxis, where we describe the numbers as population in thousands. Lastly, we describe the series - which expects an array, along with the relevant data. It passes in the countries variable from before.

Lastly, we have the last variable which is a function to create a new highcharts chart with our options passed in as the first argument.

We'll focus on the ethercraft variable here. Right now, this is what we have for ethercrafts in the AJAX file:


But these are all constants. What if (and we have) an Ethercraft class in our ActiveRecord, which also describes these 5 currently and would like to use that? Imagine if there's more than just 5 ethercrafts, like how there's more than 5 different genres of music and we wanted the graph to reflect that?

We'll first need to get all the ethercrafts in ActiveRecord first, and present it as an array of the names of Ethercrafts. Otherwise, we'll just have an ActiveRecord Relation object that describes all the items or the Object References to the Ethercraft items, or worse.

Firstly, in the controller where the graph will be displayed, we can use the following private method and store it in a single instance variable, such as @ethercrafts:



With that done, next we'll need to change the variable in our AJAX file to take in the collection of the different types of Ethercrafts from ActiveRecord (via our instance variable, @ethercrafts). To do that, we can go to our application.html.erb, and add in our header:


Then we should change the ethercrafts reference in the AJAX file and point it to window.ETHERCRAFT. And this should do it! Right?





...no? It doesn't work, because the syntax for performing ERB is expecting quotation marks around that. So we'll go do that:


And this will make:

...what on earth? Oh, because it expects an array, right? So adding a bracket surrounding the variable should close it up nicely:





This should do it:



 Not exactly what we expected. We got the names of the ethercrafts all there/ But they're covered in " before and after!

What exactly happened here? The long and the short of it is that during the processing via Ruby/ActiveRecord -> ERB -> Javascript -> HTML, the array of our ethercrafts were in this form:

["Soulreaving", "Enforcement", "Invoking", "Evoking", "Empty"]

However, through all that, the quotation marks were read and parsed into the " text. So how do we fix this? Let's take a look at the source code while we're at it (very important thing to do as well, it's a good habit I've picked up.).


Our window.ETHERCRAFT has our ethercraft array within the array we added earlier. That's strange! However, this does explain some things. When JavaScript expects an array of strings, like when we are trying to define the X-Axis Categories for Highcharts expects quoted strings separated by commas. Now, the quotes don't exist when Javascript reads it, so we end up with the " mess or a plain syntax error prior to adding our overarching quotes or array boxes. But now, we end up with this.

So how do we fix it? A handy function to use is to use the raw form of our HTML to be read into the Javascript, which we'll add to our ERB file as we render our ethercrafts variable:

We remove the quotations and the array, as our instance variable already contains our square array and our strings separated by quotes and covered with individual quotation marks for each through our method in the controller. This is exactly the format Javascript will expect, so this is what we get:





Hooray! We've done it.

And so ends this post where I describe my morning. I get closer to making highcharts usable for census data, and learn how to move raw data from Rails to ERB to JS to HTML. A very nifty lesson, overall.

Hope this helps. Comments, criticisms and advice are wholly welcome!


No comments:

Post a Comment