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!


Thursday, 25 September 2014

Starting Highcharts

I was looking into highcharts due to the popularity of presenting data on websites and apps nowadays. Highcharts is part of a series of JavaScript based apps that features interactive display along with HighStock and HighMaps - and they look pretty sleek.

As you highlight your mouse over the bars, a small box describes exactly what you want. And the implementation thus far seems to be so simple. I'll be working on this over the next few days to see how I can put in variables as data - the site has a way for people to get started.

But, keep in mind that on Ruby on Rails we like to compartmentalize our scripts and sources. Normally, you'd put in your head tags  (as instructed in the Highcharts tutorial:)


<'script' src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></'script'>
<'script' src="http://code.highcharts.com/highcharts.js"> </'script'> 


But there is now a gem for highcharts, highcharts-rails. So all we'd need is to add this gem to our gemfile and we can just plug in highchart scripts and methods into our Ajax file:


In Gemfile:
gem "highcharts-rails", "~> 3.0.0"


In app/assets/javascripts/application.js, add to the end:
//= require highcharts
//= require highcharts/highcharts-more


And then we're all set. This above example was as easy as making a new div with the id 'container' anywhere on my HTML, and using the following, copy pasted code from the highcharts example into your JQuery code:



From the look of things, we could probably put in variables in the array. This is looking like straightforward JQuery. I will definitely be meddling around here to get what I want for statistics. It definitely seems like a versatile and very powerful chart API.

Wednesday, 24 September 2014

The little things between form and 'form'

After a long trip following my graduation from Metis, I went back proper into a routine this week. And today, I learned a great tidbit about how to render forms in Rails, very simple but it saves me a lot of time from now on.

I used to write the following:


<%= render 'form', form: form %>

For rendering a form partial. I couldn't just not put in the 'form: form' part because it would always say that form doesn't exist in the partial (in the form partial, there was - obviously, a form with it's associated fields designated as form such as form.text_area, and so on).

However, one of my colleagues pointed this out to me that I could just do:

<%= render form %>

The difference? By removing the quotations, Rails magic will immediately do the previous line I put up for me. That is very convenient, and actually solves a lot of my hassles (I've always wondered how people just write render form - and now I realize it's just the quotes!).
 

Sunday, 31 August 2014

HabitRPG

So I was wandering around Hacker News today, and I came across something exactly what I was hoping to do last year!

Enter HabitRPG, a to-do list with a gamified twist. It has dailies, to-dos, habits (good and bad) and the ability to reward yourself. Basically, you have an avatar, with stats and experience points - things you'd expect in an RPG - and as you do tasks, dailies or good habits, you gain exp and money. With money, you can buy new costumes or pets for your avatar - very addictive things that are used to be so common all over the internet (NeoPets, that dragon egg signature thing on forums?). It's genius, because people who are attracted to such a feature will find themselves much more motivated.

So how does one motivate oneself to do it further? Social networking, of course. It integrates with Facebook - which is something I have to check to be sure, but if it does what I think it does with Facebook, you'll be able to see each other's progress and that usual peer pressure does the rest. It's kind of like how you brag to others about what you're doing - you're much more likely to follow through after!

You can also form parties, too, and take on various quests/challenges. In parties, you can see each other's progress (another form of peer pressure), and challenges involve giving yourself new tasks between you and your party that you share and do.

It's great! I'm definitely going to use this between bouts of Trello (They have a Trello board too for things they need doing, to boot.)

On another note, they need people to contribute! People to spread word of mouth, people to write, people to art, and people to code! For code, they use Angular JS  for both web and mobile (apparently, it makes it very easy to transfer between web and mobile codes.). They use Mongoose for the database and ExpressJS for their API server. Some things to look into, I'm sure if I want to contribute. It's a worthwhile effort, I think, and Angular is pretty big lately.

In the meantime, though, I'm going to go gain a few levels as I complete tasks. :D

Friday, 29 August 2014

Start of something new

With Wednesday, Metis' career day behind us, we're finished with the course - but there's tons of resources we still have access to. However, we're now fully-fledged junior developers at this point.

It's been an incredible ride; and while I've said that several times throughout the blog, it still hasn't changed one bit. I've learned a lot, and we've been taught much. At the start, I only had what I gathered from my experiences in RMXP and video game modding, and now I can make full fledged web apps, the design principles to make them be powerful, flexible and lean, the various languages and tools to build them on and the drive and resources to move on.

It's wonderous what 3 months can achieve, and I really have gotten used to the idea of how what I have now is able to create things to help people with. I can express my creativity and my desire to help others or myself through what I've learned.

Creative writing is one of my favourite pastimes, and in that regard, I've found that coding isn't too different from it. In a sense, we are creating things - we are building something as a sort of creative need within us as builders. There's many ways to tell a story, or to paint a picture, or to write code that all convey or do the same thing. The processes that we go through and the challenges we face are all very similar to one another. We have to figure out how to overcome the hurdles of burn out, how to motivate ourselves, or those moments where we feel like we can't come up with anything valuable or something people would want, or times where we think we're weaker than our peers.

In that regard, coding requires the same dedication or passion as writing. I think that's why I've fallen in love with this particular art. While creative writing will be a pastime for me, I feel that it serves me best as my tool of self expression and introspection. Code, on the other hand, is my way to really create things for others. I have a lot of projects lined up that I think of daily as I ponder about family, friends and colleagues that could use my talents to make a few of their problems easier.

Definitely, now that I walk out of thoughtbot's office as a Metis graduate, I feel like I can code a lot more challenging apps, and these challenges are things I'd be glad to tackle.

Friday, 15 August 2014

Using Carrierwave and Fog

Following up installing RMagick in my previous post, I added Carrierwave and Fog. For the most part, instructions on getting Carrierwave running with Fog are in line with what I gathered in this blog post by JavaHabit. However, there's a few things to keep in mind:

  • Once you get your fog.rb generated, be sure to move it to your config/initializers folder.
  • If you plan on pushing your app to heroku, don't link your secret keys within the fog.rb file, you should install the dotenv-rails gem, make a .env file, put the keys inside it, then be sure to use ENV.fetch in the fog.rb file to obtain the keys remotely. Add .env to the gitignore file.
  • Restart your server. Additionally, it's best to convert the hash syntax within the fog.rb file to the newer rails style (if you use version 4).
  • Common error fixes: restart the server, remove the region line, and keep the fog.rb file to the bare minimum (delete mostlines to make most things set to their defaults). Those are the most common SO answers I've found.

Basically:

Add the dotenv-rails gem in your gemfile:

gem 'dotenv-rails'

In your fog.rb file, trim it down as much as possible and make the key hashes point to an ENV.fetch of the keys you need:

CarrierWave.configure do |config| 

config.fog_credentials = {
 provider: 'AWS',
 aws_access_key_id: ENV.fetch("AWS_ACCESS_KEY_ID"),
 aws_secret_access_key: ENV.fetch("AWS_SECRET_ACCESS_KEY"),
 }
 config.fog_directory = "bucketname"
 config.fog_attributes = {"Cache-Control'=>'max-age=315576000"}
end

In your .env file, make the following definitions for env variables:

AWS_ACCESS_KEY_ID=accesskey 
AWS_SECRET_ACCESS_KEY=secretaccesskey

In your gitignore file, add the uploads folder and .env to avoid uploading your images (if any) and secret keys onto github:

/public/uploads
.env

Lastly, in ImageUploader:

storage :fog

And that should set Fog up for your Carrierwave. Hope it helps!

Wednesday, 13 August 2014

Installing RMagick on Windows

Today while working on our project, I was facing trouble installing RMagick. It was - as expected, a windows issue, and while most guides on troubleshooting were old and out of date, a more recent Stack Overflow response (January 2014) more or less pointed out the issue was that Windows might not be supported in the more recent versions of ImageMagick with RMagick. So the solution was to use older versions when it worked, and it definitely solved my issue in installing it.

To sum up and quote the answer by Dany Khalife:

Uninstall ImageMagick and re-install a previous version that works with your Ruby setup.
This is what worked for me :
Keep in mind the version numbers! I'm running on Ruby 2.0.0 and it worked just fine. Be sure to use the following command, assuming ImageMagick was installed in C:/ :


gem install rmagick --version=2.13.2 --platform=ruby -- --with-opt-lib=c:/ImageMagick/lib --with-opt-include=c:/ImageMagick/include 

And that's all there is to it. 'bundle install' should work just as well, too for the rails project. Hope this helps!