Lightening Talk Redux

On December 19, my friend, Anisha Ramnani gave a lightning talk on the implementation of sessions in Sinatra. What follows is a summary of that discussion. Please note that Anisha’s writing is italicized and mine is normal.

Last week we learned how to use Sinatra, which according to Wikipedia, “…is a free and open source software web application library and domain-specific language written in Ruby.” It’s really great because we are able to move away from primarily working in Ruby and also involve some CSS styling and HTML.

The first assignment we were given was to replicate the website emergency compliment. We were challenged to create a simple web application that generated a new compliment, color and image each time a user refreshed the site page. This led to the question: how could we write our web application to avoid the same images and colors appearing on after another?

Having just finished learning object-oriented programming (OOP) in Ruby, my esteemed colleague Anisha and I were stoked. We knew that each visit to our site would be an instance of the class Compliment. To instantiate each object, we created the constants COMPLIMENTS, IMAGES, COLORS and called .sample on each constant in the initialize method. At the very least, this ensured a random sampling for each visit to our site.

But we were only halfway there. We had to keep track of state for all of our compliments and avoid duplicates. To that end, we created a history constant, shovelling each instance into it via self in our initialize method. Armed with a record of each compliment, we thought we could avoid dups by comparing the index value of the last compliment (HISTORY[-2]) with each initialized compliment (HISTORY[-1]).

In order to check duplicates, we created a method called self.check_duplicates that compares the second to last element in the history array with the most recent element in the constant HISTORY array. While the colors for the most recent compliment and the previous compliment were the same, we would initialize a new complement color to replace it until the colors were different.

We soon realized that even though this method worked within Ruby, we could not use this same logic in Sinatra. The class was not remembering the history when it was run in the sinatra app class. This is because once the page was refreshed, the logic was forgotten.

The idea of state within the newer, more expansive parameters of a Sinatra web application took us completely by surprise, but left us intrigued. How could we avoid those pesky dups? With a little help from our teacher and classmates, we stumbled upon the idea of sessions.

Sessions, like cookies, store information about a user’s interaction with a web app, and programmers can define which variables a session stores, such as the last color displayed on a page.

The first thing to know about sessions is that you must explicitly enable them in your app. Easy enough, just add ‘enable :sessions’ right after you define your class. Second, sessions store data in hashes, so you read and write their data as key-value pairs. That’s basically all you need to get started.

To implement sessions in our logic, we used an if/else statement to check whether a session key existed. If not, we instantiated a new compliment and set the session key color equal to that compliment’s color. With the session key, we were now keeping state (at least for the variable compliment color) for each user’s first visit to our site.

In the else portion of our logic, for each successive visit, we instantiated a new compliment and compared its color with the value of the last session via a while loop. So long as the last session color matched the new compliment color, the logic reset it by sampling the COLORS constant in our class.

We then set the session[:last_color] to the compliment color, so that we can use this method for the following instances of the app class.

Presto! We had solved the mystery of keeping state in the Sinatra Application. 

This intel on sessions leads to the grand question: why does it matter? Sessions matter, because they serve as a way to store information in web applications. The example base case can be applied to other web applications where we need to be able to store information of a particular instance of a website.

Keeping state in your web applications is fundamental to how the internet works. Each time you visit an e-commerce site, it’s sessions that keep track of the items in your shopping cart. Without them, your cart would be empty each time you visited a new page.

So through the simple concept of creating a compliment page, we were able to learn more about sessions! Our page was able to work successfully, and we hope to continue to apply the sessions logic elsewhere.

Advertisements

DEPRECATED DEPRECATED DEPRECATED

Eek. Check out this unholy web page

What could be the problem? It seems we have a web page with nested h3s, which is a big no-no in HTML5. The resulting effect is a cascading size increase for each successive header.

Using the web inspector’s hourglass feature, when you hover over a header and compare it with its predescessor, you can see that nesting h3s is causing the browser to nearly double the width and height of each h3.

According to W3schools, “since users may skim your pages by its headings, it is important to use headings to show the document structure. H1 headings should be used as main headings, followed by H2 headings, then the less important H3 headings, and so on.” Nesting h3s defy’s the logical document structure of HTML5, which carefully manages the hierarchy of a page for users’ ease of browsing and developers’ ease of styling.

Given that the DOCTYPE says HTML 3.2, I estimate this page dates back to 1997. I recommend rewriting the page to comply with HTML5 standards.

Capture your Regex

If coding is about manipulating strings, than one of its essential tools is regular expressions (regexes). Up until now, I have been traversing and parsing strings via .split, .each, .select, .find_index, .unshift, .push, .join, .collect — all of which are fascinating ways to rearrange data — but regexes can be a better alternative, especially when once basic iteration techniques are mastered.

The ideal case for employing regexes presented itself yesterday while working on a team project to parse through SubRip (.srt) file data set. .srt files are used to synchronize video subtitles with specific intervals of time. Because they are always the same length, .srt files are a great candidate for capturing data with regexes. .srt files consist of strings in timecode format hours:minutes:seconds,milliseconds, plus the subtitle.You can apply the same regex to any file and it will always capture the right data in the right place.

A big challenge is understanding how to access captured data, which is returned in a MatchData object that has its own special set of traversal tools. The example below uses several methods for catching data inside the MatchData object.

The example below uses regular expressions to parse through a string in timecode format hours:minutes:seconds,milliseconds. This format is used in SubRip (.srt) files to denote the interval of time that a subtitle should appear in a video. Note that this example builds on an already great tutorial from rubylearning.com

Need to polish up on your regex? Here are some great resources.

1. In his book The Bastards Book of Regular Expressions” Dan Nguyen defines regexes as “a way to describe patterns in text, either to find or to replace.”

2. Rubular is a great way to learn regex through trial and error.

3. Regex Crossword is fun!

Fun fact: If there exists at least one regex that matches a particular string, then there exists an infinite number of other regex that also match it.