This is a short guide on how to use the Reddit API to create a cakeday-site, for beginners. A cakeday is the day someone joined the community Reddit, so it’s like an online birthday. My final version is called tellmemycakeday.com, but this guide will create a small version of that one.

If you are having trouble seeing how the code looks in its entirety, it can be found at the bottom of the post.

My mind was set to try out JavaScript. The time hade come, and I wanted to do something useful. Well, something you could use. Well, something that did something. So why not create a page that tells you your Reddit cakeday? It’s been done before, but what hasn’t? So I thought I’d share how I did it so that everyone can try, ‘cause it was fun. It’s so quick and nimble, results come fast and you get amazed at the possibilities.

Getting the data

The first step is to figure out how to get hold of a specific user’s account creation date. What’s great about Reddit is that all their data is available via a public API. What that means is that they are openly showing how their site works, and that anyone can create a Reddit application just by looking at their public and open source code. The part we’re going to use is about the users.

The lookup is done via an AJAX call to Reddit. What Reddit wants is a string that contains information on which user and how you want the data. It looks like this:

http://www.reddit.com/user/someuser/about.json?jsonp=?

The next thing we need is a JavaScript file to execute our code. I’m using jQuery, and this is all the code needed to fetch the right response and print it in the console:

1
2
3
4
5
6
7
$(function(){
    $.getJSON('http://www.reddit.com/user/someuser/about.json?jsonp=?',
    function(data){
        console.log(data);
    });
});

Put it in a file with the ending .js. This makes a GET-request for the user named “someuser” and then prints that user in the console (the console.log(data)-part).

Create an HTML-file containing the following:

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
        <script type="text/javascript" src="app.js"></script>
        <title>Cakeday</title>
    </head>
    <body>
    </body>
</html>

The first script tag links to a CDN hosting jQuery, the second to your own, new JavaScript file. If you now open your HTML-file in a browser (I’ll assume you use Chrome), you can see the exact response! Right-click, choose “inspect element” and open the console (to the right).

Here is what I saw:

Reddit response

All the data is there! You can see how much link and comment karma this user has, if it is a mod and, what’s important to us, when it was created. Now it is a matter of using this data in a creative way.

Formatting the date

So, the date 12011825216 is not very readable. It’s the date formatted as UNIX time, the number of seconds since the 1st of January 1970. We need to change it into something prettier! And I used Moment.js to do just that. By just utilizing that small library the number is transformed into something a human can understand.

1
var createdDate = moment.unix(data.data.created);

This creates a manageble date that can then be used to figure out how many days are left until the next cakeday. The part inside the parenthesis is the date we got from Reddit, and moment.unix tells Moment.js that it is a date in unix-format.

The next part can be a bit difficult for someone who, like me, is slightly mathematically challenged. How do you find out how many days there are left? The created-date is sometime in the past, all you need is the day and month. So I replaced the year in the createdDate with the current year. Unless, off course, your cakeday has already happened this year, then we need the next year.

We put this bit of code inside a function that takes the date the user was created as parameters and returns the number of days left to the next cakeday. I think the code is more readable and managable when divided into neat functions.

1
2
3
4
5
6
7
8
9
10
var caluclateDaysLeft = function(createdDate) {
    var currentYear = moment().format('YYYY');

    var nextCakeday = createdDate.year(currentYear);

    if(nextCakeday < moment()){
        nextCakeday = nextCakeday.add('years', 1)
    }
return nextCakeday.diff(moment(), 'days');
}

Showing the days left to the user

Now we have calculated the date and can view it in the console. What is the next step? Well, instead of displaying it in the console we want to put it in the browser window. This is done by manipulating the HTML, using jQuery. jQuery can help us select elements in the HTML and insert out information.

What we want is to display the days left to the visitor, and to do this we need to add an element to the previously created index.html.

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
        <script type="text/javascript" src="moment.min.js"></script>
        <script type="text/javascript" src="app.js"></script>
        <title>Cakeday</title>
    </head>
    <body>
        <p id="result"></p>
    </body>
</html>

We’ve added a link to the Moment.js-file and a paragraph to hold the result.

In our JavaScript-file we add a line that puts the number of days into the paragraph.

1
$('result').text(daysLeft);

It finds the element with the id “result” and then sets the text to what we found before.

Getting a username from the visitor

The site is not very usable if you can’t choose which username you want to look up. How to create this behaviour? We need to create a form that can take input from the visitor and then use that input in our JavaScript.

First, we modify the index.html to look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
        <script type="text/javascript" src="moment.min.js"></script>
        <script type="text/javascript" src="app.js"></script>
        <title>Cakeday</title>
    </head>
    <body>
        <form id="cakedayForm">
            <input type="text" placeholder="Your username" id="userName">
            <br />
            <button type="submit" class="btn btn-success">Submit</button>
        </form>
        <p id="result"></p>
    </body>
</html>
</form>

That adds a form with an input field and a submit button. This is all we need!

In the JavaScript we need to grab the text from the input-field and run the function when the user presses the button. The code below is triggered when the “submit”-event happens, which is exactly what we want. It takes the value written by the user and then runs the function that displays the days left to that particular user’s cakeday.

1
2
3
4
5
$(document).on("submit", '#cakedayForm', function(event) {
    event.preventDefault();
    var user = $("#userName").val();
    displayDaysLeft(user);
});

So now we actually have all the parts needed to have a site that takes a Reddit username and displays how many days there are left to that users’s cakeday!

Putting it all together

All we need to do is put it all together, like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$(function(){
    $(document).on("submit", '#cakedayForm', function(event) {
        event.preventDefault();
        var user = $("#userName").val();
        displayDaysLeft(user);
    });

    var displayDaysLeft = function(user) {
        user = $("#userName").val();
        var userUrl = "http://www.reddit.com/user/" + user + "/about.json?jsonp=?";

        $.getJSON(userUrl, function(data){
            var createdDate = moment.unix(data.data.created);
            var daysLeft = caluclateDaysLeft(createdDate);
            $('#result').text(daysLeft);
        });
    };

    var caluclateDaysLeft = function(createdDate) {
        var currentYear = moment().format('YYYY');
        var nextCakeday = createdDate.year(currentYear);

        if(nextCakeday &lt; moment()){
            nextCakeday = nextCakeday.add('years', 1)
        }
        return nextCakeday.diff(moment(), 'days');
    };
});

This does not, however, take into account what to do when the user doen’t exist, or if the visitor doesn’t write anything in the input, but that’s left as an exercise to the reader. And the site also looks awful! The code can be found on Github and a live version is running on tellmemycakeday.com/tinyversion. And if you want to have a look at the extended version, prettier and with error handling, you can find it on tellmemycakeday.com, this is also avaliable on github!

A beginner’s guide to locating the Candidate Key and Normal Form of a relation.

There are many systems and algorithms that can help you find the candidate key of a particular relation. What these don’t tell you is how much easier this can be if you just learn to draw appropriate boxes and arrows! Granted, you might not look like the coolest kid in a group of hardened database programmers if you do this. But we are all beginners in the, you know..beginning.

Swallow your pride, this is a really good and clear way! This article is meant for those of you who are starting out with relational databases and normalization. I hope you know the purpose of normalization and what the different normal forms are.

Every relation has one or more candidate keys. A candidate key (CK) is one or more attribute(s) in a relation with which you can determine all the attributes in the relation. Later on, when you implement the relation in a database, the candidate key, or one of the keys, will be the primary key of a relation. Knowing the candidate key is also needed to determine the normal form of the relation. But how do you find it? Well, you can either look all professional and use algorithms. Or you can draw it!

 

An example of how to draw you way to the candidate key

Let me show you with an example. This relation deals with movies and actors.

Movie(title, year, genre, genre-description, direcor, director-home-country)

First, we have to list the dependencies. Which attributes are dependent on which? An arrow means that by knowing the one to the left, you know the one to the right.

title —> year

title —> genre

title —> director

genre —> genre-description

director —> director-home-country

So what I do is that I make a box for each of the attributes and then simply add arrows to represent dependencies.

Find the candidate key

Now it’s extremely easy to locate the least amount of attributes you need to determine the rest of the relation: Title! No arrows are pointing at title and all the other boxes have arrows that originate from title. Therefore: The candidate key of this relation is Title, and that makes title a primary attribute (an attribute that is part of  candidate key). More on primary attributes later, when we continue on to deciding the normal form. This example was pretty basic and simple, let’s continue on to something a bit trickier. And let’s also leave this with attributes that makes sense behind; my imagination was stretched a litte too thin by the last example… Consider the relation:

R(A, B, C, D, E)

where

A —> B

B  —> A

B —> C

D —> A

Then you’ll get this drawing:

Find the candidate key

No arrow is pointing at neither D or E, so in order to determine all the attributes in this relation you’ll need to know both D and E, since nothing can determine either of them. This gives you a composite key. Candidate key: {D, E}. C and E together. I’ll show just one more example before moving on to using this knowledge. A trickier and larger one.

R(A, B, C, D, E, F, G)

A —> B

B  —> {A, C, E}

C —> {B, F, D}

F —> {D, G}

The curly brackets are just a short hand. Instead of saying A —> B, and A —> C, you write A —> {B, C}.  Find the candidate key

Here you actually have several candidate keys. If you know A you can determine the entire relation, but that is also true for B and C. From B you can get to all the other boxes by just following arrows, the same for C and A! So the result is several candidate keys, A, B and C.

 

Using the drawing to determine the normal form of a relation

The drawings are also a great help on the way to find out which normal form a relation has. All you have to do is know how to draw boxes, arrows and what the rules of the normal forms say.

So let’s try it with a relation.

R(A, B, C, D)

A —> B

B —> C

C —> {B, D}

Which gives this drawing:

Find the normal form

The Candidate Key of this relation is A, since that’s all you need to determine the rest of the relation. That makes A the only primary attribute (an attribute that is part of a candidate key). But what of the normal forms? I will go through them one by one.

  • First normal form. Are all the attributes atomical? Well, yes! None of them are more than one, so to speak.
  • Second normal form. Is there a non primary attribute that’s determined by parts of any candidate key? This implies that we need a composite candidate key (one that consist of two or more attributes, like in the second example above), and since we don’t, this can’t be true and the relations is therefore in 2nd normal form. To have a relation that is not in 2nd normal form, there would have to be an arrow pointing from an attribute that is part of a candidate key, towards an attribute that is not part of a candidate key.
  • Third normal form. Does a non primary attribute exists that’s determined by another non primary attribute? Yes, in this case there is! There is an arrow from B to C and both of them are non primary attributes, so this relation is not in 3rd normal form.

What about 4th and Boyce Codd and all the other normal forms, then? Well, a relation that’s in 4th normal form must fulfill the rules regarding the 4th normal form as well as all the others “leading up” to it. So, if it breaks the rule for 3rd, it can’t be in 4th.

One last example.

R(A, B, C, D)

A —> {B, D}

B —> {A, C}

C —> B

The drawing:

Find the normal form

And the candidate key will be A, B and C.

  • First normal form. Are all the attributes atomical? Still yes.
  • Second normal form. Is there a non primary attribute that’s determined by parts of a candidate key? No, the same as above. The only non primary attribute is D and it’s not determined by parts of a candidate key.
  • Third normal form. Does a non primary attribute exists that is determined by another non primary attribute? No, no two non primary attributes determine each other. In this case we only have one, so it can’t happen.
  • Boyce-Codd normal form. Are all the deteminates candidate keys? Or, as I like to think of it, are all attributes to the left of the arrows candidate keys? You just look at where the dependencies are listed (above the drawing) and see if all those to the left are candidate keys. In this case, they are.
  • Fourth normal form. Deals with the problems that can arise from having multivalued dependencies, and seeing as there are no multivalued dependencies, we can assume that it is good to go for the 4NF!

So, the relation is in 1 to 4th normal form and Boyce-Codd, and we’ll leave the rest for another time! I hope this article has made the topic of candidate keys and normal forms somewhat clearer. There are probably many other ways to solve this problem, but this has worked great for me.

Feel very free to contact me with questions or suggestions.

/SQ