Now that the basic setup of my new NFL project has been completed, I can move on to the next step. Though the inspiration for starting this new project has a variety of suggestions on how to get a side project going, for me this is a bit more than just a side project, so I’ll be proceeding differently than they suggest.

For instance, the project does have goals, but the goals don’t really have deadlines per se as suggested. The goals are to learn new or strengthen existing skills while getting the project to the point of being a viable application to launch that others might find interest in. For many bootcamps or tutorials, the goal is usually to build a clone of something that already exists (Craigslist, AirBnB, Twitter to name a few), and within that process you learn a variety of useful skills that would be needed for any developer working in most Rails applications. Though I am on twitter, I’m not a big user of most of the sites used in such tutorials, so the idea of recreating them has never held my interest, or scratched an itch as the inspiration article suggests. I understand the clone concept as a teaching mechanism, but I know over time that I will lose interest, so I have to find projects that appeal to me and hopefully lead me to build existing skills and learn new ones at the same time. As such, my hope is that this project will help me:

  • Strengthen my skills in writing and executing tests efficiently and effectively
  • Delve deeply into my query writing for rails. Be it through Active Query or other means, an application like this will require complex multi-join queries.
  • Work on my UI/UX skills, laying things out, determining how best to write custom CSS, and how to best work with the Bootstrap grid setup.
  • Deploy an application to a live server, via Digital Ocean probably. This blog is currently deployed on Heroku which does a lot of the work that I should learn how to do myself.
  • Learn how to have an application run a set task at a set interval (for the NFL it is once a week, which is one of the reasons to work on this versus my NBA application) automatically.
  • Work with javascript libraries to make my application more interactive. One library I for sure want to work with is D3, which is a library that can be used to present data graphically.

The above is not a complete list, but I think it provides a good start of what I’ll need to strengthen (or learn) to get to a point where I’d be happy with the finished product.

The MVP (Minimum Viable Product) point is still formulating in my head, but I think I have an idea where that point would be, and it would require a few of the bullet points above to at least be closer to completion to achieve, so that’s a good thing. However, before I can even start working on most of those points, certain starting pieces as I’ll call them need to be built. Those pieces include two Models that are vital, but pretty static. Once the information is loaded into them, they won’t change that often, if ever. This data represents divisions and teams. In this article, we’ll work on setting up and testing the Division Model.

Building the Division Model

Each team in the NFL is part of a division. Each division is part of a conference. There are two conferences in the NFL, the AFC and the NFC, and each conference has four divisions, and though it wasn’t always like this, the divisions in each conferences are the same:

  • East
  • North
  • South
  • West

So the database table will have 8 entries, consisting of one of two conference options and one of four division options. It probably seems pretty silly to break this out separately but it makes sense to me from a normalization point of view to isolate something like this and Rails use of relationships will make it easier when I’m looking for all the teams from a given division or conference.

Two attributes are therefore needed for the Division Model; the name of the division and the conference that the division is in, and both are of the string/text variety. This is an easy this to do using the Rails model generator followed by a quick rails db:migrate to process the migration that results from using the generator.

So the framework for the division information now exists, but there are no restrictions on the values that can be entered, and so validations must now be created. I usually test the implementation of validations on my Models by creating the corresponding controller, and views, and testing user created and edited records. However, as stated earlier, the data in this Model (or the Team Model) will not require a lot of attention/modification once set up, so I will use Model testing with shoulda-matchers to get the validations set up.

If you read through the documentation for shoulda-matchers on the github page, you’ll see that there’s a variety of built in commands for testing a variety of common concepts in Rails, including validations. My plan is to use shoulda-matchers to test the Division Model, and the Team Model on, as this data will be entered once (probably via seeds) and altered very little, if at all, so building a real user interface to be able to add and update isn’t needed right away, and will save me time in regards to reaching the MVP

The first validations are easy, I just want to validate for the presence of the conference and name attribute in a given record. Using validates_presence_of from shoulda-matchers, I write my failing test, and then to get the failing tests to pass, it’s a simple matter of adding of adding two lines to the division.rb file in your app/models directory:

validates :name, presence: true
validates :conference, presence: true

Ok, so that was easy, basic stuff, but now we get onto the validations that are less common.

Validating that the name attribute is unique, but only in relation to conference attribute

Unique attributes are a common thing in applications. You don’t want the same email registered twice in your newsletter list, the same user name in your discussion forum, or the same item number in your inventory system, but sometimes the uniqueness is a little less basic than just it can only occur once. For instance, I want the name of the division to be unique, but only in relation to the conference. You can’t have two east divisions within the NFC but you can have an east for the nfc conference and an east for the afc conference. (Not only can you, you must have them both.)

Exploring the shoulda-matchers validates_uniqueness_of I found that I want to test that the division attribute is scoped_to the conference attribute, and thus the RSpec test looks like:

it {should validate_uniqueness_of(:name).scoped_to(:conference)

This however, is not perfect, because in Rails uniqueness is very strict, so case matters. By default, case sensitivity is set to true when you validate uniqueness. Personally, I think this is a mistake. More often than not, uniqueness is case-insensitive (email, user name above for instance, would you allow different versions just on the basis of which letters were and weren’t capitalized?), but that’s not my call, so the shoulda-matcher requires a slight tweak:

it {should validate_uniqueness_of(:name).scoped_to(:conference).case_insensitive

One of the helpful Rails learning tools is the apidoc website. It has a lot of sample code, with options, for most Rails commands you can use. So, finding the way to write the uniqueness validation on the name attribute so that it is dependent on the conference was pretty quick. The information in the second code example makes it pretty clear:

validates uniqueness: {scope: :conference, case_sensitive: false}

My previously failing (red) test now passed (green) and it’s on to the next validation test.

Validating that the conference is limited to specific options

Even though it’s unlikely that the conference attribute of these records will ever need to be changed, I feel for completeness, and so I know how to do it, that a validation needs to be set up so that it is limited to either nfc or afc. After a quick web search to verify it, I believe the correct way to implement this is with validates_inclusion_of. Using the [shoulda-matchers](] documentation on this, the test is set up as:

it {should validate_inclusion_of(:conference).in_array(["nfc", "afc"] )}

Running the test shows that I did write it correctly (always a concern the first time for me), it runs the proper check, and it fails, as it should. So we’ve got the red, and it’s time to get the green. The apidock gives me the basics, and I just have to alter it to fit within the way I’ve learned to write multiple validations on one attribute:

validates :conference, presence: true, inclusion: {in: %w(nfc afc)}

Running the test file again and the failing test now passes, so it’s green. Not a lot of refactoring to be done right now. As previously said, this is a pretty simple, basic Model that won’t have a lot of work done on it once it’s set up (seeding it), but, still, it is a necessary foundational piece that is not set up and ready to take data.

So the final step, as always, is the version control. Add the changes and commit locally and then push to the github repository. Then it is on to the next step, building out the Team Model.

Note: If you’ve read earlier articles, you’ll notice that the flow of this article is slightly different. Usually when I’m writing my articles, I attempt to write it so it’s understandable to my primary readers, my family and my wife, who don’t really know much coding. In this article, I tried a different tack and just focused (more so at least) on the code itself. Additionally, I originally planned to create both the Division and Team Models in this article, but I also decided to split that into two pieces so that the article would be shorter, and that I could have something to publish sooner rather then later.