{"action":"created","comment":{"url":"https://api.github.com/repos/olinjs/olinjs/pulls/comments/22692306","id":22692306,"diff_hunk":"@@ -1 +1,364 @@\n-#Class 3\n\\ No newline at end of file\n+#Class 3 - Express, Templating, and MongoDB\n+\n+##Express\n+Now that we've explored Node.js a little, we will abstract the details away with the [Express](http://expressjs.com/) development framework. Before, in the Node Beginner's Book, our code looked a lot like this:\n+```javascript\n+var http = require(\"http\");\n+\n+http.createServer(function(request, response) {\n+  response.writeHead(200, {\"Content-Type\": \"text/plain\"});\n+  response.write(\"Hello World\");\n+  response.end();\n+}).listen(8888);\n+```\n+\n+Now let's see what the same app would look like using Express. To start we'll set up a new application using `npm init`. This will ask you a series of questions that will populate your `package.json` file, you can use the defaults for all of them. This file manages many things. If you publish your module on npm (like any of the modules which you `npm install` are published) this file will include the meta information about your module. We won't get into that much in this class, but that's why it seems like there are a lot of unnecessary fields. The main purpose we will use the package.json for is dependency management.\n+\n+After you exit the init setup, run `npm install express --save`. If you check your package.json again, you'll see the following was added:\n+```javascript\n+\"dependencies\": {\n+    \"express\": \"^4.10.6\"\n+  },\n+```\n+The `--save` argument will add the module to your list of dependencies and is generally a good thing to use whenever adding a new module. If you just forked a cloned a project that has its dependencies listed you can simple run `npm install` to install the required dependencies (at the right versions) for that project.\n+\n+Now that we're set up, create a file named `app.js` and and paste in the following:\n+```javascript\n+var express = require('express');\n+var app = express();\n+\n+app.get('/', function(req, res){\n+  res.send('hello world');\n+});\n+\n+app.listen(3000);\n+```\n+Inside the folder you created the `app.js` file, run the command `node app` to start the server. Go to `http://localhost:3000` in your web browser and you should see the following:\n+```\n+hello world\n+```\n+Awesome! You just ran your first application using Express!\n+\n+Express makes writing web servers in Node much easier. Here are some of the important differences between the examples you did in the book and Express:\n+* Routing. Instead of trying to parse the URL the user is at ourselves, we can just tell Express to match an individual path with a function.\n+* Sending a response. Express takes care of setting many obvious response headers for you. Express will also handle sending files like images, music, audio, or `.html` files from a folder easily.\n+* Handling templates. We haven't gotten here yet, but we'll touch on this later.\n+Let's go back to our `app.js`. We want more than just hello world. Let's make Express show the string `hello olin` when we go to `http://localhost:3000/olin`.\n+\n+Below the `app.get('/',...` statement, add the following:\n+```javascript\n+app.get('/olin', function(req, res){\n+  res.send('hello olin');\n+});\n+```\n+\n+So what does `app.get` do? It tells express that every time we have a `GET` request from a client (the browser). We'll learn more about this in Routing.\n+###Routing\n+Routing is the process of serving up different pages for different urls. When you go to www.mycoolsite.com/ your computer goes out on the internet and asks mycoolsite's server for a page. Mycoolsite's server then sees that request and sends back information to your computer in the form of html. This html is then rendered on your browser.\n+\n+If you go to www.mycoolsite.com/ mycoolsite's servers obviously can't send you the same data it sent www.mycoolsite.com/olin. So mycoolsite's servers needs to differentiate `/` from `/olin`. This process is known as routing.\n+\n+In the Node Beginner Book, we did routing through something like\n+```javascript\n+var pathname = url.parse(request.url).pathname;\n+route(handle, pathname, response, request);\n+```\n+Instead of writing the code to handle the route ourselves, Express does it for us with these statements:\n+```javascript\n+app.get('/', function (req, res){\n+  res.send('hello world');\n+});\n+\n+app.get('/olin', function (req, res){\n+  res.send('hello olin');\n+});\n+```\n+These two routes we created are for the index page (/) and the olin page (/olin).\n+\n+So what does `app.get` do? It tells express that every time that particular route (the first string argument) receives a `HTTP GET` request, we want to execute the anonymous function (the second argument). `HTTP` lets you perform different types of requests for a particular route, and these types are called **methods**. `GET` is just one of the methods you can perform, and is the most common (every time request an image or a script for example). You can [view the other types of HTTP methods on wikipedia](http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods). But for now, let's only consider these two:\n+* `GET` returns a resource (such as an image or an html page). This is used for when your browser wants to read information from a server. Parameters and options are communicated in the url through the path (`/olin`) and query string parameters (`?pageid=12&button=2&coolsetting=super`) which you may recognize from various websites.\n+* `POST` is used for when your browser wants to send information over to the server. For example, when you fill out an online form, that data is sent over to the server as `POST` data. This information is sent in the request header, is not visible in plain-text and can be encrypted.\n+\n+### Organizing an Express Application\n+Express offers a tool called the `express-generator` to get a new directory up a running.\n+```sh\n+express expressintro\n+\n+   create : expressintro\n+   create : expressintro/package.json\n+   create : expressintro/app.js\n+   create : expressintro/public\n+   create : expressintro/public/images\n+   create : expressintro/public/stylesheets\n+   create : expressintro/public/stylesheets/style.css\n+   create : expressintro/routes\n+   create : expressintro/routes/index.js\n+   create : expressintro/routes/users.js\n+   create : expressintro/public/javascripts\n+   create : expressintro/views\n+   create : expressintro/views/index.jade\n+   create : expressintro/views/layout.jade\n+   create : expressintro/views/error.jade\n+   create : expressintro/bin\n+   create : expressintro/bin/www\n+\n+   install dependencies:\n+     $ cd expressintro && npm install\n+```\n+This creates a series of directories `public`, `routes`, and `views`. The public directory is used for client side assets such as images, stylesheets, and client side javacript. Views are used to store template files which we will cover later. Routes, which we will focus on first, contain all the routing logic of our applications.\n+More often then not, I find the generated app provides more structure and example files then you actually want and you end up deleting much of it. Feel free to explore the generator if you're curious, but for now we'll steal the folder structure and build the contents ourselves.\n+\n+Create this folder structure in the same directory as your `app.js` file by running `mkdir views routes public public/images public/javascripts public/stylesheets`. The create a new files `index.js` in the `routes` folder. This is where we will add some of the main routing logic for our app. You will often see another file like `users.js` in the routes folder which would contain routes that might manage login, logout, view profile, or other actions like that. You may even see `routes/cat.js` in your near future!\n+\n+To move the \"hello world\" routing into this new structure, paste the following into the `routes/index.js` file:\n+```javascript\n+var home = function(req, res){\n+  res.send(\"Welcome home!\");\n+};\n+\n+module.exports.home = home;\n+```\n+\n+Then replace the contents of `app.js` with:\n+```javascript\n+var express = require('express');\n+var index = require('routes/index');\n+var app = express();\n+\n+app.get('/', index.home);\n+\n+app.listen(3000);\n+```\n+Note that this time we `require` the new route file as the variable `index` then instead of defining the route function inline we just write `index.home`, which is the function we defined in the index.js file. This structure helps to keep the `app.js` file a bit leaner and makes it more clear where in the project our routes are defined.\n+\n+### Application Configuration and Useful Settings\n+\n+There are some initial configurations we want our app to do, such as running on a specific port, using routes, and setting up the public directory as well as some useful tricks to add to our `app.js` file.\n+\n+First, were going to install 3 more modules that are used in pretty much every Express app: `npm install --save body-parser cookie-parser morgan`.\n+Next we'll use them in `app.js` by doing the following:\n+Add these lines to the top of the file, next to the rest of the requires:\n+```javascript\n+var path = require('path');\n+var logger = require('morgan');\n+var cookieParser = require('cookie-parser');\n+var bodyParser = require('body-parser');\n+```\n+We add `path` here which we did not need to install because it is included within node. It gives us some useful directory path functionality you'll see in a second.\n+Add these lines of configuration below the line `var app = express();`:\n+```javascript\n+app.use(logger('dev'));\n+app.use(bodyParser.json());\n+app.use(bodyParser.urlencoded({ extended: false }));\n+app.use(cookieParser());\n+app.use(express.static(path.join(__dirname, 'public')));\n+```\n+This sets up some basic command line logging functionality using the [Morgan](https://github.com/expressjs/morgan) module, request body parsing, cookie parsing, and establishes the `public` directory as a static folder. This means that going to `http://localhost:3000/images/foo.jpg` will load the file `./public/images/foo.jpg` without any additional work from us. The same will work for javascript files, stylesheets, static html files, or anything else you may want to serve directly.\n+\n+If you run the app again (`node app`) upon navigating to http://localhost:3000 you will notice a new line in your console:\n+```\n+GET / 304 6.892 ms - -\n+```\n+This is Morgan logging the request. This will really come in handy while trying to debug in the future.\n+\n+Now go ahead and copy the image `cat.jpg` from the `expressintro/public/images` folder in this directory and place it in your new images folder. Then navigate to http://localhost:3000/images/cat.jpg. That is your static folder doing work!\n+\n+## Templating\n+\n+Now I imagine you may be asking yourself, *\"This is a web-dev course, right? Where's the HTML?\"* Well its coming, but doing it smart is not as simple as putting some `<p>` tags in a file and calling it a day. We will be using a technique called templating. Templating allows us to put some logic behind what is otherwise entirely a layout language. This will greatly reduce the overall quantity of HTML you write, thereby reducing errors, and making it much easier to make a change to an element that appears on many pages in your app. Most importantly however, it allows us dynamically customize the contents of our HTML. Think about Facebook profiles. When you load yours, you are looking at a static page of HTML. But Facebook's servers aren't full of files called `ben-kahle-profile.html`, and `evan-simpson-profile.html` that wouldn't exactly scale very well. They have a single profile template into which they inject your personal profile information, render it as HTML and then send it to your browser. Let's learn the basics!\n+\n+First off, we will be using [Handlebars](http://handlebarsjs.com/) as a templating engine. The default templating engine of Express is actually [Jade](http://jade-lang.com/). We're going to use Handlebars for a few reasons:\n+* It more closely resembles the HTML result you will see on the client. Some people consider this a negative, but we like it and it can make debugging your views *much* easier. It also makes it easier while you are learning HTML.\n+* It supports pre-compiled templates and client side rendering. We won't get to these for a while, but they provide some great performance boosts and some awesome flexibility when it comes to designing and building dynamic front-ends.\n+* Jade's whitespace dependency and style can be a bit too dense and harder to understand. Handlebars may be more \"cluttered\", but it can also be very nicely structured and layed out in an easy to read manner.\n+\n+At the end of the day, templating engines-like most things-come down to personal preference, and that's why we're forcing you to like Handlebars! (At least for the next couple weeks).\n+\n+### Making Express Render Handlebars\n+\n+To get Express to render handlebars, as well as to add some useful templating features which we will get into later, we are going to use the [Express-Handlebars](https://github.com/ericf/express-handlebars) module. So go ahead and `npm --save install express-handlebars` to get it installed.\n+\n+Now two more things to know about are layouts and partials.\n+* Layouts: Basically meta-templates. They are handlebars documents that allow you to create a wrapper around all the templates that use them.\n+* Partials: Basically mini-reusable templates. They are handlebars documents that can be written once and \"included\" within other templates. (ei. a navigation bar that appears the same on every page)\n+\n+We're going to build a layout and leave utilizing partials as an exercise for later.\n+\n+To render a template the first thing we want is a base layout. To start we'll make a very simple one:\n+```html\n+<!DOCTYPE html>\n+<html>\n+  <head>\n+    <meta charset=\"utf-8\">\n+    <title>Express Intro</title>\n+  </head>\n+  <body>\n+    {{{body}}}\n+  </body>\n+</html>\n+```\n+This is some of the boiler plate for HTML with the center bit `{{{body}}}`. That signifies where templates will be inserted into this layout.\n+Go ahead and copy that code into a file `main.handlebars` and put it in a new folder `layouts` within the `views` directory of your application.\n+\n+Now for the template itself. Starting off simple:\n+```html\n+<h1>Welcome Home!</h1>\n+```\n+Save that in a file called `home.handlebars` and put in the `views` directory as a sibling to the new `layouts` directory you just made. Your folder structure should look like this:\n+```\n+.\n+├── app.js\n+└── views\n+    ├── home.handlebars\n+    └── layouts\n+        └── main.handlebars\n+\n+2 directories, 3 files\n+```\n+All of this organization is completely customizable, but we'll leave it as the defaults for now.\n+\n+Now let's hook it all up!\n+\n+Add the line `var exphbs  = require('express-handlebars');` to the top of your `app.js` file. Then add these two lins after the `var app = express();` line:\n+```javascript\n+app.engine('handlebars', exphbs({defaultLayout: 'main'}));\n+app.set('view engine', 'handlebars');\n+```\n+Note that you're setting the default layout for the application to the `main.handlebars` file you just created. You can change the layout for a single template at render time with a simple option.\n+\n+Lastly, within the `index.js` routing file, replace:\n+```javascript\n+res.send(\"Welcome home!\");\n+```\n+with\n+```javascript\n+res.render('home');\n+```\n+Restart your server, visit http://localhost:3000 and behold your template!\n+\n+At this point you are basically just writing plain HTML, let's fix that!\n+Start by adding the following to your `home.handlebars` template:\n+```html\n+<ul>\n+{{#each classes}}\n+  <li>{{this}}</li>\n+{{/each}}\n+</ul>\n+```\n+Then change the contents of your `index.js` route again. This time to this:\n+```javascript\n+res.render(\"home\", {\"classes\": [\n+  \"Olin.js\",\n+  \"other class 1\",\n+  \"other class 2\",\n+  \"other class 3\"]\n+});\n+```\n+The second parameter that we are passing to the `render` function is the *context* for the template. That means that the word `classes` in the handlebars file is looking for an array named `classes` and it will create a new list item for *each* of the elements in the array. There's plenty more power in templates and we'll see them shortly.\n+\n+## MongoDB\n+\n+Node has the ability to store some information as variables. But all of the variables are stored in the process memory. If you restart the server (or the server crashes) the data will be wiped away. If you are storing information from users or information based on user input, we need a more permanent solution. That's very persistent storage comes in. A file, like `data.txt`, is a form of persistent storage. It can be written to, read from, and maintains information regardless of whether your server is running or has long since stopped. But files aren't useful for much more than storing log information because of their organization. When we want to retrieve data from persistent storage quickly, we need a solution like a database!\n+\n+MongoDB is a NoSQL database. It stores data in JSON-like documents, is relatively performant and offers useful features for production level systems. We're going to use it for these reasons, but also because it is very easy to integrate with Node and doesn't require learning too much about data storage. Alternatives, for example the ubiquitous MySQL, are also very common database solutions, but tend to take a bit more time to get set up in a Node environment and do not have as easy abstraction layers to shield you from interacting with the database directly (through the wonders of SQL). You will likely see them in any internships or jobs doing web-dev, but MongoDB more than suits our purposes and will teach you the basics of data storage without taking a couple weeks of class time to get comfortable with. So, let's get Mongo running and see what we can do with it:\n+\n+```sh\n+sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10;\n+echo \"deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen\" | sudo tee /etc/apt/sources.list.d/10gen.list;\n+sudo apt-get update;\n+sudo apt-get install -y mongodb-org\n+```\n+\n+Once installed, start the database by running:\n+```sh\n+sudo service mongod start\n+\n+```\n+If you ever run into errors connection to your database, ensure the `mongod` service (mongo daemon) is still running, and restart it if necessary.","path":"classes/class3/README.md","position":279,"original_position":279,"commit_id":"58ca48c9d3fbc23cc8072b4c545055e4b0eed536","original_commit_id":"58ca48c9d3fbc23cc8072b4c545055e4b0eed536","user":{"login":"EvanSimpson","id":1757661,"avatar_url":"https://avatars.githubusercontent.com/u/1757661?v=3","gravatar_id":"","url":"https://api.github.com/users/EvanSimpson","html_url":"https://github.com/EvanSimpson","followers_url":"https://api.github.com/users/EvanSimpson/followers","following_url":"https://api.github.com/users/EvanSimpson/following{/other_user}","gists_url":"https://api.github.com/users/EvanSimpson/gists{/gist_id}","starred_url":"https://api.github.com/users/EvanSimpson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EvanSimpson/subscriptions","organizations_url":"https://api.github.com/users/EvanSimpson/orgs","repos_url":"https://api.github.com/users/EvanSimpson/repos","events_url":"https://api.github.com/users/EvanSimpson/events{/privacy}","received_events_url":"https://api.github.com/users/EvanSimpson/received_events","type":"User","site_admin":false},"body":"connection -> connecting","created_at":"2015-01-08T23:41:04Z","updated_at":"2015-01-08T23:41:04Z","html_url":"https://github.com/olinjs/olinjs/pull/4#discussion_r22692306","pull_request_url":"https://api.github.com/repos/olinjs/olinjs/pulls/4","_links":{"self":{"href":"https://api.github.com/repos/olinjs/olinjs/pulls/comments/22692306"},"html":{"href":"https://github.com/olinjs/olinjs/pull/4#discussion_r22692306"},"pull_request":{"href":"https://api.github.com/repos/olinjs/olinjs/pulls/4"}}},"pull_request":{"url":"https://api.github.com/repos/olinjs/olinjs/pulls/4","id":26800498,"html_url":"https://github.com/olinjs/olinjs/pull/4","diff_url":"https://github.com/olinjs/olinjs/pull/4.diff","patch_url":"https://github.com/olinjs/olinjs/pull/4.patch","issue_url":"https://api.github.com/repos/olinjs/olinjs/issues/4","number":4,"state":"open","locked":false,"title":"class3","user":{"login":"benkahle","id":3596325,"avatar_url":"https://avatars.githubusercontent.com/u/3596325?v=3","gravatar_id":"","url":"https://api.github.com/users/benkahle","html_url":"https://github.com/benkahle","followers_url":"https://api.github.com/users/benkahle/followers","following_url":"https://api.github.com/users/benkahle/following{/other_user}","gists_url":"https://api.github.com/users/benkahle/gists{/gist_id}","starred_url":"https://api.github.com/users/benkahle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/benkahle/subscriptions","organizations_url":"https://api.github.com/users/benkahle/orgs","repos_url":"https://api.github.com/users/benkahle/repos","events_url":"https://api.github.com/users/benkahle/events{/privacy}","received_events_url":"https://api.github.com/users/benkahle/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-01-04T22:31:12Z","updated_at":"2015-01-08T23:41:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"990b4b8b474f01adffd1a8afe754ca70b0538422","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/olinjs/olinjs/pulls/4/commits","review_comments_url":"https://api.github.com/repos/olinjs/olinjs/pulls/4/comments","review_comment_url":"https://api.github.com/repos/olinjs/olinjs/pulls/comments/{number}","comments_url":"https://api.github.com/repos/olinjs/olinjs/issues/4/comments","statuses_url":"https://api.github.com/repos/olinjs/olinjs/statuses/58ca48c9d3fbc23cc8072b4c545055e4b0eed536","head":{"label":"olinjs:class3","ref":"class3","sha":"58ca48c9d3fbc23cc8072b4c545055e4b0eed536","user":{"login":"olinjs","id":3213751,"avatar_url":"https://avatars.githubusercontent.com/u/3213751?v=3","gravatar_id":"","url":"https://api.github.com/users/olinjs","html_url":"https://github.com/olinjs","followers_url":"https://api.github.com/users/olinjs/followers","following_url":"https://api.github.com/users/olinjs/following{/other_user}","gists_url":"https://api.github.com/users/olinjs/gists{/gist_id}","starred_url":"https://api.github.com/users/olinjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/olinjs/subscriptions","organizations_url":"https://api.github.com/users/olinjs/orgs","repos_url":"https://api.github.com/users/olinjs/repos","events_url":"https://api.github.com/users/olinjs/events{/privacy}","received_events_url":"https://api.github.com/users/olinjs/received_events","type":"Organization","site_admin":false},"repo":{"id":28649083,"name":"olinjs","full_name":"olinjs/olinjs","owner":{"login":"olinjs","id":3213751,"avatar_url":"https://avatars.githubusercontent.com/u/3213751?v=3","gravatar_id":"","url":"https://api.github.com/users/olinjs","html_url":"https://github.com/olinjs","followers_url":"https://api.github.com/users/olinjs/followers","following_url":"https://api.github.com/users/olinjs/following{/other_user}","gists_url":"https://api.github.com/users/olinjs/gists{/gist_id}","starred_url":"https://api.github.com/users/olinjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/olinjs/subscriptions","organizations_url":"https://api.github.com/users/olinjs/orgs","repos_url":"https://api.github.com/users/olinjs/repos","events_url":"https://api.github.com/users/olinjs/events{/privacy}","received_events_url":"https://api.github.com/users/olinjs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/olinjs/olinjs","description":"The second offering of Olin.js in the spring of 2015","fork":false,"url":"https://api.github.com/repos/olinjs/olinjs","forks_url":"https://api.github.com/repos/olinjs/olinjs/forks","keys_url":"https://api.github.com/repos/olinjs/olinjs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/olinjs/olinjs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/olinjs/olinjs/teams","hooks_url":"https://api.github.com/repos/olinjs/olinjs/hooks","issue_events_url":"https://api.github.com/repos/olinjs/olinjs/issues/events{/number}","events_url":"https://api.github.com/repos/olinjs/olinjs/events","assignees_url":"https://api.github.com/repos/olinjs/olinjs/assignees{/user}","branches_url":"https://api.github.com/repos/olinjs/olinjs/branches{/branch}","tags_url":"https://api.github.com/repos/olinjs/olinjs/tags","blobs_url":"https://api.github.com/repos/olinjs/olinjs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/olinjs/olinjs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/olinjs/olinjs/git/refs{/sha}","trees_url":"https://api.github.com/repos/olinjs/olinjs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/olinjs/olinjs/statuses/{sha}","languages_url":"https://api.github.com/repos/olinjs/olinjs/languages","stargazers_url":"https://api.github.com/repos/olinjs/olinjs/stargazers","contributors_url":"https://api.github.com/repos/olinjs/olinjs/contributors","subscribers_url":"https://api.github.com/repos/olinjs/olinjs/subscribers","subscription_url":"https://api.github.com/repos/olinjs/olinjs/subscription","commits_url":"https://api.github.com/repos/olinjs/olinjs/commits{/sha}","git_commits_url":"https://api.github.com/repos/olinjs/olinjs/git/commits{/sha}","comments_url":"https://api.github.com/repos/olinjs/olinjs/comments{/number}","issue_comment_url":"https://api.github.com/repos/olinjs/olinjs/issues/comments/{number}","contents_url":"https://api.github.com/repos/olinjs/olinjs/contents/{+path}","compare_url":"https://api.github.com/repos/olinjs/olinjs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/olinjs/olinjs/merges","archive_url":"https://api.github.com/repos/olinjs/olinjs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/olinjs/olinjs/downloads","issues_url":"https://api.github.com/repos/olinjs/olinjs/issues{/number}","pulls_url":"https://api.github.com/repos/olinjs/olinjs/pulls{/number}","milestones_url":"https://api.github.com/repos/olinjs/olinjs/milestones{/number}","notifications_url":"https://api.github.com/repos/olinjs/olinjs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/olinjs/olinjs/labels{/name}","releases_url":"https://api.github.com/repos/olinjs/olinjs/releases{/id}","created_at":"2014-12-30T23:29:53Z","updated_at":"2015-01-08T01:29:32Z","pushed_at":"2015-01-08T23:29:48Z","git_url":"git://github.com/olinjs/olinjs.git","ssh_url":"git@github.com:olinjs/olinjs.git","clone_url":"https://github.com/olinjs/olinjs.git","svn_url":"https://github.com/olinjs/olinjs","homepage":null,"size":356,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":4,"forks":1,"open_issues":4,"watchers":0,"default_branch":"master"}},"base":{"label":"olinjs:master","ref":"master","sha":"0dbdbe7c1402cb8b35620b7ae3ed73bffebf96af","user":{"login":"olinjs","id":3213751,"avatar_url":"https://avatars.githubusercontent.com/u/3213751?v=3","gravatar_id":"","url":"https://api.github.com/users/olinjs","html_url":"https://github.com/olinjs","followers_url":"https://api.github.com/users/olinjs/followers","following_url":"https://api.github.com/users/olinjs/following{/other_user}","gists_url":"https://api.github.com/users/olinjs/gists{/gist_id}","starred_url":"https://api.github.com/users/olinjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/olinjs/subscriptions","organizations_url":"https://api.github.com/users/olinjs/orgs","repos_url":"https://api.github.com/users/olinjs/repos","events_url":"https://api.github.com/users/olinjs/events{/privacy}","received_events_url":"https://api.github.com/users/olinjs/received_events","type":"Organization","site_admin":false},"repo":{"id":28649083,"name":"olinjs","full_name":"olinjs/olinjs","owner":{"login":"olinjs","id":3213751,"avatar_url":"https://avatars.githubusercontent.com/u/3213751?v=3","gravatar_id":"","url":"https://api.github.com/users/olinjs","html_url":"https://github.com/olinjs","followers_url":"https://api.github.com/users/olinjs/followers","following_url":"https://api.github.com/users/olinjs/following{/other_user}","gists_url":"https://api.github.com/users/olinjs/gists{/gist_id}","starred_url":"https://api.github.com/users/olinjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/olinjs/subscriptions","organizations_url":"https://api.github.com/users/olinjs/orgs","repos_url":"https://api.github.com/users/olinjs/repos","events_url":"https://api.github.com/users/olinjs/events{/privacy}","received_events_url":"https://api.github.com/users/olinjs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/olinjs/olinjs","description":"The second offering of Olin.js in the spring of 2015","fork":false,"url":"https://api.github.com/repos/olinjs/olinjs","forks_url":"https://api.github.com/repos/olinjs/olinjs/forks","keys_url":"https://api.github.com/repos/olinjs/olinjs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/olinjs/olinjs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/olinjs/olinjs/teams","hooks_url":"https://api.github.com/repos/olinjs/olinjs/hooks","issue_events_url":"https://api.github.com/repos/olinjs/olinjs/issues/events{/number}","events_url":"https://api.github.com/repos/olinjs/olinjs/events","assignees_url":"https://api.github.com/repos/olinjs/olinjs/assignees{/user}","branches_url":"https://api.github.com/repos/olinjs/olinjs/branches{/branch}","tags_url":"https://api.github.com/repos/olinjs/olinjs/tags","blobs_url":"https://api.github.com/repos/olinjs/olinjs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/olinjs/olinjs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/olinjs/olinjs/git/refs{/sha}","trees_url":"https://api.github.com/repos/olinjs/olinjs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/olinjs/olinjs/statuses/{sha}","languages_url":"https://api.github.com/repos/olinjs/olinjs/languages","stargazers_url":"https://api.github.com/repos/olinjs/olinjs/stargazers","contributors_url":"https://api.github.com/repos/olinjs/olinjs/contributors","subscribers_url":"https://api.github.com/repos/olinjs/olinjs/subscribers","subscription_url":"https://api.github.com/repos/olinjs/olinjs/subscription","commits_url":"https://api.github.com/repos/olinjs/olinjs/commits{/sha}","git_commits_url":"https://api.github.com/repos/olinjs/olinjs/git/commits{/sha}","comments_url":"https://api.github.com/repos/olinjs/olinjs/comments{/number}","issue_comment_url":"https://api.github.com/repos/olinjs/olinjs/issues/comments/{number}","contents_url":"https://api.github.com/repos/olinjs/olinjs/contents/{+path}","compare_url":"https://api.github.com/repos/olinjs/olinjs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/olinjs/olinjs/merges","archive_url":"https://api.github.com/repos/olinjs/olinjs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/olinjs/olinjs/downloads","issues_url":"https://api.github.com/repos/olinjs/olinjs/issues{/number}","pulls_url":"https://api.github.com/repos/olinjs/olinjs/pulls{/number}","milestones_url":"https://api.github.com/repos/olinjs/olinjs/milestones{/number}","notifications_url":"https://api.github.com/repos/olinjs/olinjs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/olinjs/olinjs/labels{/name}","releases_url":"https://api.github.com/repos/olinjs/olinjs/releases{/id}","created_at":"2014-12-30T23:29:53Z","updated_at":"2015-01-08T01:29:32Z","pushed_at":"2015-01-08T23:29:48Z","git_url":"git://github.com/olinjs/olinjs.git","ssh_url":"git@github.com:olinjs/olinjs.git","clone_url":"https://github.com/olinjs/olinjs.git","svn_url":"https://github.com/olinjs/olinjs","homepage":null,"size":356,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":4,"forks":1,"open_issues":4,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/olinjs/olinjs/pulls/4"},"html":{"href":"https://github.com/olinjs/olinjs/pull/4"},"issue":{"href":"https://api.github.com/repos/olinjs/olinjs/issues/4"},"comments":{"href":"https://api.github.com/repos/olinjs/olinjs/issues/4/comments"},"review_comments":{"href":"https://api.github.com/repos/olinjs/olinjs/pulls/4/comments"},"review_comment":{"href":"https://api.github.com/repos/olinjs/olinjs/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/olinjs/olinjs/pulls/4/commits"},"statuses":{"href":"https://api.github.com/repos/olinjs/olinjs/statuses/58ca48c9d3fbc23cc8072b4c545055e4b0eed536"}}}}