Thursday 2 October 2014

Making Highcharts Series from ActiveRecord items

Following up on the previous blog, where we successfully linked categories on the X-Axis with an Active Record table, we'll move on to the next step, that is actually taking data to be used and displayed on the Y-Axis.

But first, a few things:

The method I described the other day to iterate through all ethercraft names in our controller is actually not necessary. Someone (thank you!) pointed out to me that a method does exactly what I was doing already: .pluck.



So instead of above, in the controller action where this method was called I just did:


@ethercrafts = Ethercraft.pluck(:name)

And I can safely remove this method and all.

Next, we'll need to make sure we can actually get data for our series. In the previous example, we used a census to obtain the number of people practicing a certain ethercraft by country. So, we'd need to make sure that we can link countries generated via ActiveRecord in case we add/remove more countries.

Let's change this a little (because I already have Race set up as a selection for characters) and make our graph just draw a census of number of ethercraft practitioners by race. We just need to make a race table, along with the associated actions to add/edit races in the app with the actions, and it'll be fairly similar and ready like ethercrafts.

Now, the challenge next is finding the data we need to actually add the series and have actual values for the graph itself.

If you recall the format for generating series in highcharts:






The series itself is expecting:
  •  An array, that contains
    •  hashes for each series, with each containing key/value pairs of
      • a name for the series, and
      • data, which contains
        • an array that contains counts for each category on the graph
Keeping that in mind as we make our ethercrafts-by-race census, we'd need to have a hash for each 
race that has data for how many of that race practice an ethercraft.

But since we live in an era of databases and charts and linked information pulled from repositories, we'll generate that data ourself.

In this sandbox app, a fantasy character generator, I've got characters, and each character has a race, and an ethercraft. To make this data count work, I'll link characters to their race and ethercraft choice in ActiveRecord via foreign keys. Each character belongs_to one race and belongs_to an ethercraft.

Once that was done, the next step was very simple: to generate the series, we'll just need to add to our controller a new method that'll iterate through characters, iterating each ethercraft for each race.


This method, defined in the controller will take all races and ethercrafts and iterate through each ethercraft for each race, finding characters that meet the current race/ethercraft combination. The glory of map is that, when used in this way, it generates an array the way we want it to. It creates an array for the counts for ethercrafts in order of their id, and fixes them into the race_ethercraft array for each race. At the end of the ethercraft map, it makes a hash taking the current race's name and the array generated for a data key, then that is automatically added into an array for the results for mapping the races. Once that's all done, we'll have every race with a hash that has the numbers we're looking for.

Now all that's left is to fix up our HTML and our AJAX file:


AJAX:



And we'll boot up our chart again:


Presto! Of course, this was made after I quickly rigged up a bunch of characters in the database, and even then - it still looks empty. But if you had real data to add from a database, this would be one way to do it.

The issue arises, that I can think of is in how that method was written: assuming I had a lot of data to go through, would the chart load as quickly? One way to find out is to actually get a lot of stock data. And that's something I'll look into for next time.

Hope this helps, and as always, comments and critiques are appreciated!

No comments:

Post a Comment