Today I’ll be covering the methodologies and lessons learned from my second project at AirPair, Sevendaysports. Before I begin, I wanted to let you know that you can skip all of this reading and take this site out for a demo spin. The account details and url is at the bottom of this post.
Let me first say that this was a project that I vastly underestimated the power and complexity of Rails on, it is also the project where I learned a ton and had the most fun with to date! The topics I learned during project Sevendaysports includes, Test Driven Development of both models and controllers, class methods and scopes. I also filled in some wholes in my fundamental understanding of how Rails controllers work. I have a lot of AirPair mentors to graciously thank for sticking with me as I slowly overcame these hurdles and increased my knowledge of each topic.
Test Driven Development
TDD is a software development process where a developer or pair of developers follow a red, green, refactor cycle to build an application. Test driving an application using the red, green, refactor cycle goes something like so. Before your first line of application code, you write a test spec for one of the data models knowing it will fail (because no code has been written yet). The failing test we write describes a behavior, and once we verify that our test is failing typically by typing
rspec spec followed by the model, controller, or routes we’re testing, we can run our specs once more. The intent being to write as little code as possible to get a particular spec to go from fail to pass or red to green. The refactor comes about after we have code that functions as we’d like, but maybe could be a little more concise and/or easier to read for future developers.
I recently had to wipe and re-install my Mac OS, and when I cloned my projects from Github and ran tests for sevendaysports I got the following errors:
LoL! I’m laughing out loud because I remember not to long ago, that seeing literally all of my specs failing would send an alarming charge throughout my nervous system. But thats not even close to being the case ever since investing some valuable time with my AirPair mentors. I realized pretty quickly this time that I probably didn’t have my database migrated since I’ve wiped and reinstalled my mac’s OS. Lets take a look at an error to paint a more vivid scenario:
The illustration above shows this error for the second time. The first time these errors occurred, I ran
rake db:reset, which performs a
rake db:drop (which removes the database from the current environment), followed by a
rake db:setup (which runs
rake db:schema:load followed by
rake db:seed). After seeing this error the second time I knew that I needed to prepare my test database. This is because Rails has three database environments.
One is for development, and the convention is to name this db
app_name_dev. Then there is a production database that we can name using the same convention
app_name_prod. And for the situation in the above illustration, since we’re actually running tests, Rails has a test database that is typically named
app_name_test. Here is the command I ran and the results of running all 86 specs one more time.
There has been a host of additional education that I’ve received about writing specs, here is a short list of things that I’ve written about.
- Intro to Test Driven Development: Rspec & FactoryGirl
- Rspec Part2: Test driving school
- Code Review: Model specs with Edward Anderson
- Controller Specs: with Mark Simoneau
- Rev up your Rails: A short look at Guard & Zeus
- TDD your Ruby project: Ruby off Rails setup
- Framework agnostic TDD – Intro to Test::Unit methods
I’ve learned so much about Test Driven Development, but I understand and am looking forward to growing more proficient in this area over time. One of my mentors Edward once mentioned that learning to become very good at test driving my applications will increase my opportunities with most any employer prospect. One of the highlights of my TDD education was learning to ping pong pair with Mark Simoneau. I’m certainly looking forward to the day when I begin to learn and use the Vim and Tmux development environment. That ping pong pair session certainly left me with a huge sense of wow-factor!
Advanced Active Record 101
Active Record is an Object Relational Mapper that allows us to communicate with our database, where a class is represented by a database table, and the objects created by the class are rows inside of this database table. Here is a link to a pretty good resource I found online. To be honest, I’m not entirely certain on the difference between Active Record and Advanced Active Record. I am certain however that my confidence and familiarity of query basics using Active Record has been on a consistent rise. Here is a post of me covering this topic in brief detail. My education of querying via the Active Record ORM quickly led me to some idiomatic Rails conventions to provide all of the power with minimal effort. Welcome to…
It is convention in Rails to use a scope instead of a class method and here is an insightful blog post about the slight differences between scopes and class methods. For me one of the most convenient pleasures of using scopes is that they are chainable.
Lets pull a hypothetical scenario from the Sevendaysports project.
Proceeding with our hypothetical scenario, we can just focus on lines: 16 through 24 for now.
Since we are in the Event model we can assume for all of these scopes that we’ve created deal with an event. The scope on line:16 is saying that we can use the keyword
:by_user to find all of the events created by a specific user. We use the
user_id to locate the appropriate resource representation and can order these events by name. Ascending order is the default, so we don’t necessarily need to add it on line:16. But if you check out line:24 we can see that I’ve created orders in both Ascending and Descending manner.
Lets see if we can’t check out a scope in action!
Focusing only on the
index action defined on lines:5 through 8, we can see two instance variables which are assigned two of our scopes in the
The above example shows these scopes defined in our
Event class on lines:20 and 21. I especially like how using a scope by defining it in our models can allow our controller to delegate responsibility to the place it belongs. Now lets create that hypothetical scope chaining example.
The chained scopes assigned to the instance variables
@past_events_by_user not only provides extra functionality. The breaking down of scopes in this manner is essentially the same thing as creating modular chunks or lego blocks of code, which we can build upon in such a way as to reduce or eliminate duplicate code. DRY code anyone?
I’ve given this section a broad title as a representation of the vast amount of new knowledge and corrected understanding that I received while learning to enhance my skill-set in this area.
First off, I want to give adulation and a personal thank-you to Ryan Bigg for not only working with me to better understand some complicated controller maneuvers (for me obviously, not for him) I was having difficulty understanding, but also for taking two hours of his time at no charge to help out a newbie in need.
Here is a post I wrote based upon our AirPair together. (Theres a video of our pair at the bottom of the post)
I’m going to leave a list of what I’ve learned about controllers in the Sevendaysports project, but first I wanted to go over Rails filters.
In Rails, filters are methods that are processed either before, after, or around a particular controller action or set of controller actions. Lets see an example from our
Event class from earlier.
In lines:2 and 3 in the above image, I’m using two
before_filters. Here’s my interpretation of what these two lines mean.
I want the
private instance methods
get_teams to be ran before a particular controller action (aka a particular instance method) is processed. How will we know which action(s) we want
:get_event to run ahead of and process beforehand? The illustration showing lines:2 and 3 are a perfect example of two of the ways Rails allows us to specify.
only: will run the
:get_teams private method on
only the instance methods we specify in the array. In this case our filter will only run
[:new, :create, :edit]. The second way that rails allows us to define filter specifications is by using
except:. In line:3 the filter will run
:get_event on none of the instance methods in our
except: [:index, :new, :create]. Which one you chose is a matter of choice. I remember an AirPair mentor saying that he likes to use whichever filter specification hash allows him to write less code. I like it!
Ok, here are some of the things I’ve learned about controllers.
I remember having an opportunity to visit spain for two weeks while in highschool, but opting out and quitting our band just because I was too chicken to make the 12 hour flight (I hadn’t flown much at that point in life :)). Well thankfully because of my exposure to experts worldwide through AirPair, I had an opportunity to learn from a developer from Spain! AirPair Mentor Gleb Mazovetskiy came through big time in helping me with some alternatives to compiling assets for production. I learned more details about the asset pipeline, and was directed to the Rails docs as well as how to use the bower-rails gem which requires a Rails developer to install node and bower as the bower-rails gem depends on them.
I believe I ended up going with the default rails asset compilation strategy, but I genuinely enjoyed looking into an alternate strategy and learning more about the asset pipeline during my learning process.
Here are a few links of some of the lessons I have learned in this area of focus.
I hope that these last two post have favorably depicted my time spent since the end of August 2013 with AirPair. Theres no question that I’m a stronger developer, albeit still a very wet behind the ears programmer, and I look forward to sharing more with you about my next project very soon!