We’ve come a long way:
public/
folder for visitors to browse.We’re able to build some pretty useful applications! For example, our translation service using Google’s Translate API and Twilio’s SMS API is pretty amazing.
Now let’s learn about a third part of the HTTP request besides the URL and the params: cookies. This is going to be the first tool in our kits that will allow us to persist information between requests.
As of now, with the HTML, Ruby, R→C→A→V, and params
that we’ve learned, we don’t have any way to store information. After we send our users the “V” in R→C→A→V, we forget everything — all our instance variables, everything goes poof at the end of each action.
However! With the addition of cookies, our first storage mechanism, we’ll be able to upgrade our little calculator to this, our new target:
https://cookies-intro.matchthetarget.com/
As you fill out the forms and browse around, then come back to a form you filled out previously, note that the calculators now remember the results of previous calculations. Handy! Let’s learn how to achieve this.
While looking at the target in Chrome, open your Developer Tools. Click the “Application” tab, then click “ Cookies” in the left sidebar, and then find https://cookies-intro.matchthetarget.com
in the list of domains.
You’re looking at your cookie jar!
Here’s the deal: each domain that you visit is allowed to store a list of key/value pairs — i.e., a Hash
— on your computer. It varies a little by browser, but in general, each domain is allowed to store 50 key/value pairs, and take up no more than 4 kilobytes of space. Each of these key/value pairs is called a cookie.
Try filling out a few of the calculator forms in the target, and watch what happens in your cookie jar. You can see that the values you enter are being saved as cookies. You can delete an individual cookie by clicking on it and pressing delete, or you can clear all of the cookies for the domain by clicking the icon at the top of the list. If you do so, the app “forgets” your calculations.
Try a few more calculations, open a new tab, and check the cookie jar there. Your cookies are all still stored, even in the new tab! You could come back tomorrow and the results of your calculations today would be waiting for you.
Now, one last thing: try visiting the target in a different browser, or from a different device. Your old calculations will not be there. Cookies are browser-specific; not computer-specific, network-specific, or person-specific.
So, when you click submit on any of the forms, you can see that the target, in addition to doing the calculation, also stores a cookie in your browser. We’ll practice how to do this shortly — it’s not really anything new; we add a key/value pair to a Hash
that Rails provides called cookies
.
The key thing to wrap our heads around is: the user’s browser sends back the entire cookies
hash with every subsequent request the user makes. In other words, after we add a key/value pair to cookies
for a particular user, every time that user visits us again, we’ll see that key/value pair in the cookies
hash (unless they clear their cookies).
So we get to treat cookies
like it’s a permanent, user-specific Hash
that persists between and across R→C→A→Vs, even though it really is not.
Okay, enough theory; let’s practice!
First, study the code for the two R→C→A→Vs that are collaborating to let visitors add two numbers together.
params
that are coming in with each request.If not, ask questions!
Now that we’re familiar with the code, if wanted to store the result of each calculation in the cookies
hash before showing the results, which line of code in which file should we do that on?
Good — now we just have to store the value in the cookies
Hash
!
We’ve been taking things out of Hash
es an awful lot, between APIs and params
, but it’s been a minute since we’ve put things in to a Hash
. Here’s a quick refresher: the method to add key/value pairs to a Hash
is Hash#store
. Unlike Hash#fetch
and Array#push
, Hash#store
requires two arguments — the value that you want to add, as well the key to associate the value to:
h = Hash.new
h.store(:color, "pink")
h.fetch(:color) # => "pink"
For more of a refresher, you might want to refresh your memory by playing around with the REPLs in the Hash Chapter.
Fortunately, we don’t have to deal directly with browser cookies ourselves, much like we didn’t have to deal directly with query strings or dynamic path segments ourselves. Rails handles parsing all of the pieces of the HTTP request for us, thank goodness, and gives us lovely, easy to use Ruby objects like params
.
Similarly, Rails provides a Hash
called cookies
, available in all controller actions and view templates; and we just get to use it. Unlike the params
Hash
, which we only get to fetch
from, we can both store
values in cookies
and fetch
them back out later. Go ahead, give it a try:
cookies.store(:most_recent_addition, @result)
Open your Developer Tools, find your app’s Gitpod domain in the cookie jar, and then submit your addition form. Voila! Your first cookie!
Now, can you display the most recent addition result on the page that shows the form to add two numbers? Give it a try.
Tasks:
/muggle_subtract
./muggle_multiply
./muggle_divide
./muggle_translate
.There are a few more nuances to browser cookies that we could go into — setting expiration dates for specific cookies, encrypting them so that they aren’t so easily visible in the Developer Tools, making them tamper-proof — but, basically, you’ve got the gist of it. It’s a small Hash
that we get to add key/value pairs to, and the user’s browser will send it back to us with every subsequent request. Cookies are like a set of permanent params
for a user.
One consequence of being able to store information in individual user’s browsers is that we can store unique values there, which allows us to distinguish visitors from one another. This unlocks a whole world of possibilities — everything from A/B testing to analytics to ad targeting. Depending on your perspective, browser cookies are responsible for vastly improving the web experience or chilling privacy invasions.
As far as we’re concerned, there’s one key thing that cookies enable that we can’t live without: sign-in and sign-out. Once we have a user’s record saved in our database table, and they come back later some day and sign in, we can plop a cookie in their browser with their ID number in it.
After that, whenever they visit our app, the very first thing we’ll do is cookies.fetch(:user_id)
, and based on that number, we’ll personalize the entire experience for them based; most likely, that value is the foreign key that will allow us to look up all of the other info that they are related to.