All very cool, but not very “real world” in the sense that most people barely know what the command line is let alone use it to run apps. Therefore, this week was our first step in turning our Ruby and TDD knowledge into working web apps we could publish and show off to friends and family.
So without further ado… welcome to the web!
What did I learn about the web?
This week’s challenges were as follows:
- Battle – a simple web browser clone of Pokemon; and
- Rock Paper Scissors – a simple web browser game of the classic game.
These challenges taught us a huge amount of information and new concepts regarding the web. To summarise but a few…
Clients and servers
At it’s heart, really simple: computer networks can be divided into clients and servers. The client is the entity that initiates a request for information. The server is the entity that responds to that request by first finding and processing that information before returning it to the client.
Model View Controller
Taking the above one step further, there is a commonly used software architectural pattern (a standard structure for organising the constituent parts of software) for implementing user interfaces in software, both on and off the web.
This is the model view controller pattern, aka “MVC“. Traditionally it was popular for graphical user interfaces (“GUI“, pronounced, “gooey“) but has become extremely popular for web apps. So what is it?
Taking the natural meaning of these words, here’s a real life example.
When you visit a restaurant you are the client.
Step 1: You arrive at the restaurant and request to view the menu.
In MVC, this is when you visit a website by typing the url into your browser. This action is a request for that website to render (i.e. display) its homepage to your browser.
Step 2: You review the menu and make a further request to the waiter/waitress for two items from the menu: one pizza and one vodka coke.
In MVC, this is you clicking on links within the current view (i.e. current page) of the website and thereby requesting further information from that website be rendered in your browser as a new view.
Step 3: The waiter/waitress writes down your request.
In MVC, these are params (i.e. the information you inputted) necessary to process your request. Params could be clicking on a link, filling in a form or selecting items from a dropdown menu etc.
Step 4: The waiter/waitress then disappears. It is the job of the waiter/waitress to control who in the restaurant is best suited to handle your order. In doing so, the waiter/waitress speaks to a member of the bar staff and to the chef.
In MVC the controller is code that takes the params input you inputted via the view (see above) and decides which model to speak to to get and/or process that information, which brings us too…
Step 5a: The bartender interprets the drink order, opens a coke and mixes it with a measure of vodka, ultimately returning the cocktail to the waiter/waitress.
Step 5b: Likewise, the chef interprets the pizza order, goes to the fridge and takes out the necessary ingredients before preparing and cooking them, ultimately returning a cooked pizza to the waiter/waitress.
In MVC 5a and 5b are further code, the model, which takes instructions from the controller as to what data to retrieve and/or process before returning it to the controller. In 5a and 5b, the bartender’s and chef’s ingredients would be the database. Databases store and organise data used in a website, e.g. user login details for logging in and out of a website like Facebook.
Step 6: The waiter/waitress as controller of your order collects the completed vodka coke and pizza and presents you with a new view, your finished order, which you are then free to eat!
In MVC this is the response to your request, a new webpage rendered with any additional information you supplied (via the params) or requested (also via the params).
And that my friend, is MVC. It’s relatively simple conceptually but can be a bit tricky to understand and implement without a real life example.
HTTP requests and responses
So I finally learnt what on earth the “http” and “https” are at the beginning of website addresses. Well http stands for HyperText Transfer Protocol. It’s a defined structure for how requests and responses are dealt with over the web. The “s” in https stands for “secure“, meaning communications between your browser and the website in question are encrypted (i.e. protected by cryptographic means).
Yeah but what is it?
Ok, so when you type a webpage URL into your browser your browser makes a HTTP GET request.
GET is a HTTP “verb” used to retrieve information from an internet resource, e.g. a video, photo, text or sound etc.
Another commonly used HTTP request is POST. POST works almost exactly the same as GET except POST is used to submit information via parameters (see above).
For instance, a POST request is used when you fill in your login details for Facebook whereas a GET request is used to retrieve your profile page and display it to you after a successful login.
GET and POST are but two verbs in HTTP: there are many others.
Aside from this basic stuff, we also learned how to interrogate HTTP requests and responses via a command line tool, httpie, which is basically a little browser you can run in your terminal.
Anatomy of a URL
Added to the HTTP learnings, we got to grips with URLs (“Uniform Resource Locators”). Most people tend to know that URL’s are the string of letters and numbers in your web address bar at the top of a browser. Most, including myself, don’t really know how they work.
Here’s an example from DOEPUD, which breaks down the anatomy of a URL.
As you can see, this URL includes a query, denoted by the
? followed by a set of parameters, in this case the doc ID for the requested video. The parameters will have likely been input by the user when clicking on a link for the video and are POSTED using the POST HTTP verb. Here’s an excellent little tutorial on URLs – well worth a read!
Sessions (without artists)
In our weekly challenge (see below) we learned how to store information in sessions. A session is a term used to refer to a user’s time browsing a website.
HTTP (see above) is stateless, that is, the server cannot differentiate between different connections of different users. Therefore, the first time a user connects to a website, a unique identifier is created for the user (how it’s done will depend on the server software) and stored in the cookies of a user’s browser. This unique identifier is known as a session ID.
From then on, the session ID is passed to the web server every time the browser makes a HTTP request. The web app then pairs this session ID with its internal database and retrieves the stored variables for use by the requested page.
Capybara is a small rodent that is often described as resembling Rafael Nadal…
But no, seriously Capybara is also testing framework for feature testing and simulating user interactions with your application. For more on feature testing and the difference between feature testing and unit testing see here.
Capybara works in conjunction with RSpec (see earlier post on RSpec). Capybara is very easy to use, understand and pick up. Essentially you write tests with super intuitive syntax such as:
fill_in "email", :with "email@example.com"
… which simulates how your user will interact with your app. In the above, you probably guessed right: this test checks for someone being able to fill in the “email” field of an online form with an email address.
Why is this good? It saves you having to manually click around your web app and fill in forms etc. You can also set it up with helper methods to simulate repetitive labour intensive user activities, e.g. sign-ups, logins and form filling.
We use this testing framework extensively at MA. It’s fantastic for testing user interactions. To use it with Ruby install the Ruby gem by following the instructions and docs here.
As always, code is best explained through practical examples and seeing it in action. If you’re interested in seeing how Capybara works, check out this fun demo.
Sinatra is a free open source web framework that can receive and respond to HTTP requests (see above). We used Sinatra to build our web apps both during the week and at the weekend. This provided a handy little introduction to web apps. Unlike Rails, Sinatra does not follow the MVC model described above.
Battle – Pokemon!
The week challenge was to create a Pokemon style battle game that could be run in the browser. To do so we used TDD Ruby and Sinatra to run our web app. This was a fairly tricky challenge and helped hone our Ruby/TDD skills whilst building these on top of our new knowledge of web application tools and frameworks.
I’m still not much of a front end whizz as I sit writing this post from the heady heights of week 10 of the main course (mainly because MA has a back end bias despite being a full stack course).
I certainly wasn’t a front end whiz back then in week 3 so sadly my app looks dreadful, yet it does capture the basic idea of switching player turns, attacking the other player and keeping tabs of each player’s Pokemon’s HP.
Check out my code here.
Rock Paper Scissors
The weekend challenge was to create a rock paper scissors game. This was probably the first app I felt proud of. Why? Well, it’s the first app that looks like a real (albeit basic looking) web app.
The user can sign up and enter their own name then take turns at choosing either rock, paper or scissors to battle against the computer’s choices.
I had a slight advantage for this challenge as I completed a Ruby kata on Codewars that required figuring out the logic for a rock paper scissors game. The logic is quite simple to code. Let me briefly explain the basic bits.
One way is to create a two-dimensional array of the player 1 “wins”, i.e. the scenarios where player 1 has a winning choice versus player 2 (the computer). These are as follows:
PLAYER_1_WINS = [[:rock, :scissors], [:scissors, :paper], [:paper, :rock]]
The above creates a constant (“PLAYER_1_WINS”) and assigns it the values in the two-dimensional array. The first element in each subarray, element
0, represents Player 1’s move and the second element in each subarray, element
1, is Player 2’s move. So using that logic, rock beats scissors in the first subarray, scissors beats paper in the second subarray and paper beats rock in the final subarray.
def winner return nil if draw PLAYER_1_WINS.include?(moves) ? player_1 : player_2 end
This method determines whether there is a winner. If there is a draw (see below), nil is returned and the third line above is not executed. Provided there is no draw, the third line is executed. The third line is saying, “do the PLAYER_1_WINS scenarios include the same pair of moves passed in to this method and, if so, return player_1 or, if not, return player 2.
(moves) parameter for the above method accepts the reader method below, which simply creates an array of player_1’s move and player_2’s move. If the order and combination of moves match those in PLAYER_1_WINS then player_1 wins and player_2 loses.
def draw player_1_move == player_2_move end
The above is the method for determining a draw, which is simply when player_1’s move matches player_2’s move.
Check out my code here. I’ve included full instructions in the README.md file for installation and playing of the game, which looks something like this:
Final thoughts on week 3!
All in all a pretty fun week. Not too intense and certainly less stressful than class extraction in week 2. As I say I was also really proud to have finally finished a working web app, albeit a simple one with terrible looking front end. For the first time I was able to show my friends and family something that lives outside of the command line, which made me feel much more like a real web developer!