In my last article, I wrote the what turned out to be the first part of my (hopefully only) two part series on displaying the standings of the nba based on the most recent game data in my application. I documented the journey from having no clue what to do to a final output that I could see through my localhost was presenting the data exactly as I wanted it to, where I wanted it to, which was a bit surprising since all those div tags made me a bit wary that I would forget to close one perhaps. So, as far as it got, it was a success. Sadly though, by the end of the very long article, a few things were still unresolved, and the goal isn’t fully completed until:

  • Proper tests are written that pass that verify what I can visually see on my local host
  • The games behind is calculated and displayed on the standings page as well (and tested for properly)
  • Rewriting the standings method to encompass both conferences, and rewrite (and refactor) the layout to deal with this concept as well, to make the code cleaner.

So that this article doesn’t go on as long as Part 1, I think (after doing the writing) that I will focus only on the first bullet point, getting the tests to work. The second (and possibly third) will be dealt with in the future so as to keep these articles slightly briefer.

Figuring out how to get the tests to pass

As stated in the previous article, finding the proper div just by counting divs wasn’t really going to work out. The original test returned an error regarding an ambitiousness to which div I wanted, and just targeting a div seemed a bit fragile if I ever wanted to change the layout. I realized I would need to come up with a way to identify where the data was stored with a bit more precision. This is easy in concept, but to make it work for every team in a way that made sense (30 teams across 6 divisions) took a little thought. At first, I thought I’d use an id, like div id="atlantic-0" would be where the first place team in the atlantic division resided. (Remember, arrays are zero-index, so the first entry is ‘0’, the second entry is ‘1’, and so forth). This seemed like it might work. In the default file type for a Rails view, it is possible to mix straight HTML with ruby code, but it can get messy. I wanted to created an id based on two changing variables, and while it could be done in the straight HTML, it just didn’t seem the best way to do it. A little research brought me to the tag view helper method. I had known in the back of my mind that something like this existed (remember, I’ve been trying to do this for a long time) but I hadn’t had need of it in a while so this refresher was important.

It seems to me that tag can be a very useful helper in the future, but if you plan on using it, pay attention to open=false being the default setting. If you do not change the open setting you’re creating a self-closing tag. For my purposes, I do have to set open equal to true, so that I can put content in the tag I’m creating and close it manually.

While reading the information on tag, I was reminded about the the use of data attributes introduced in HTML5. Though I’m not well versed in them, reading a bit about them made me think they might be more useful in not only identifying targets for my testing, but in future ideas, they might come in handy in javascript ideas.

So my plan (the second one) was to apply a data attribute for the place in the division, taking into account the ‘zero’ index of an array. That way I had a unique identifier (within the division grouping) for each team that I could target with my testing. A little research and one stack overflow question later, and I now felt I had enough to write testing code that would be able to find the specific entry I needed (when I wrote the specific code in the view of course). The targeting of the rspec test would not look like this:

   within("div#atlantic div[data-place='0']")

Targeting that location and telling the test that Toronto Raptors should be in that section solved the issue of being able to specifically target a location. And I could use this going forward to make sure the other divisions were populating properly as well. (I’ll also be able to use it for testing the other information being populated as well). Of course, to do this, not only would I have to rewrite the code that creates the div with the team information, I’d also have to alter how I’m accessing the standing data of each division. Fortunately for me that, ruby would make that pretty easy.

Arrays are pretty awesome. I don’t know much about them in other languages, but in ruby they can hold anything, you can put a mixture of data types in, you can put arrays in arrays, and they are a great way to store and move data across files, pages, etc… Ruby also provides a variety of built-in ways to work with arrays. My guess is that the most common method used on arrays is the .each method. If you want to access the data within your array, each is the way to go. I’m sure other languages use something similar (if not the same) to access data in an array. When you work with each you end up looping through each member of the array and you manipulate them during each loop before moving on to the next one. As written about previously, I store the standings for each division within an array. I manipulate that array so that the teams come in descending order of their win percentage, thus reflecting the overall division standings, and using each is great for that, but now I need a bit more information from the array that you don’t get with just each.

To populate the data-place attribute I indicated above, I need to not only access the data in each array I need to access the index (position within the array for those who aren’t programmers reading this, hi family members) of the data. I don’t know about other languages, but the folks who built ruby are quite smart and full of foresight, and they foresaw instances where you might need to access the index of an array member and not just the data itself, so they made it pretty easy for me to do what I needed to do.

It turns out (I just learned) that the Array class in ruby has a fun built-in module that comes with it. (Don’t believe me, enter your ruby terminal and type Array.included_modules and be amazed). The Enumerable module adds on some cool functions to arrays (and the Hash class as well for instance) including one called .each_with_index, and it does exactly what you would assume it does when you access an array. It gives you the data at each index, but it also gives you the index it self. Thus if I rewrite my layout from

  records.each do |team_info|

to

  records.each_with_index do |team_info, index|

Thus, on each loop I would have not only the team information but the index, which I can make use of to populate my data-place attribute using tag.

So now all I had to do was write the tag code properly, and that would be super easy, and then the first test would pass and I could write a few more, and move on to the games behind issue that I still have yet to tackle.

Sadly, it wasn’t that easy. The documentation I linked to was pretty helpful, and clear, but my lack of complete experience meant it took a few goes to get the proper code to get the tag to be created, plus, like I sometimes do, I did forget that I was dealing with bootstrap, and a row, so had to account for the columns like you do. In the end, the tag did work, and the final version looked like this:

  tag('div' {class: "col-md-3", data: { place: index }}, true)

I know that true at the end looks kind of weird, but it’s probably the most important part, and easiest to forget. Remember, by default, the tag command creates a self-closing for lack of a better term HTML tag. I need the div I create to stay open so I can put content in it, but actually, I don’t. It turns out there’s a better helper that I only just realized I could use as I was writing the previous sentence. I had skipped over the content_tag helper on the same page as the tag helper because all the examples of content produced were strings, and it didn’t click until I was writing this paragraph that I could still use content_tag and get it all done in a slightly cleaner way. I leave all I’ve written to this point because many of these articles are a documentation of the learning path, as I’m learning, so I think it’s important to keep the part about tag because the same ideas still apply, but I just chose the weaker of two options to start with. So, the final code that ends up in the view is a bit cleaner and easier to understand (to coders) as:

  content_tag(:div, team_info[:team}, class: "col-md-3" data: {place: index})

It’s possible that I’ll refactor the rest of the view to use the content_tag, because it does look cleaner without all the opening and closing divs in my view, but we’ll see

At this point, the test passed, the Toronto Raptors (which I already knew) were in the right place, but my test could find them as well. Perhaps the data-place attribute will have more use in the future, perhaps not, but for now it helped me solve the first issue I had to deal with to complete my standings method. Next, I’ll tackle the issue of dealing with games behind.