1 00:00:00,000 --> 00:00:05,000 [??] [CODE/RACER - Database Access] 2 00:00:05,000 --> 00:00:11,000 In our last set of videos, we learned how to sign in and authenticate with Facebook. 3 00:00:11,000 --> 00:00:15,000 In this video, we're going to save that information from Facebook 4 00:00:15,000 --> 00:00:18,000 to our own local database. 5 00:00:18,000 --> 00:00:23,000 In order to do this, we're going to use a project called Sequelize. 6 00:00:23,000 --> 00:00:28,000 Sequelize is an object-relational-mapper for node.js. 7 00:00:28,000 --> 00:00:33,000 In order to install it, we have to add it to our packages, 8 00:00:33,000 --> 00:00:41,000 so let's open up our package.json and add it in. 9 00:00:45,000 --> 00:00:50,000 Save the file and then run npm install to install it. 10 00:01:02,000 --> 00:01:05,000 Great. Now we have Sequelize installed. 11 00:01:05,000 --> 00:01:08,000 Let's tell our application how to use it. 12 00:01:08,000 --> 00:01:13,000 First, we'll open up our app.coffee and import it. 13 00:01:23,000 --> 00:01:27,000 Now let's take a look at the documentation and see what we do next. 14 00:01:27,000 --> 00:01:30,000 It looks like we have to configure it. 15 00:01:30,000 --> 00:01:35,000 Let's go ahead and open up our configuration file that we made earlier. 16 00:01:36,000 --> 00:01:42,000 Now we'll add our database credentials into this configuration file. 17 00:01:45,000 --> 00:01:49,000 Since we're going to be working in development, 18 00:01:49,000 --> 00:01:52,000 I'm going to create a key for development right here. 19 00:01:53,000 --> 00:01:59,000 This way, when we go to deploy it, we can specify a production environment as well. 20 00:02:21,000 --> 00:02:26,000 We're going to use the MySQL database locally to work with it, 21 00:02:26,000 --> 00:02:29,000 and we'll specify that we're logging. 22 00:02:30,000 --> 00:02:33,000 This helps a lot when trying to debug errors. 23 00:02:36,000 --> 00:02:39,000 Now let's go back and see how we initialize Sequelize. 24 00:02:46,000 --> 00:02:52,000 When initializing it, we'll give it the keys that we just specified over in our configuration file. 25 00:03:30,000 --> 00:03:36,000 In this part down here, the define key says timestamps are true. 26 00:03:36,000 --> 00:03:42,000 What that will do is add a created_at and updated_at field to each of our models. 27 00:03:42,000 --> 00:03:47,000 Every time a model is created or saved, those fields will be updated automatically. 28 00:03:47,000 --> 00:03:51,000 Now that we've got Sequelize installed, let's create a User model 29 00:03:51,000 --> 00:03:53,000 to save our Facebook data. 30 00:03:53,000 --> 00:03:57,000 I'm going to do that back on the console and make a models directory. 31 00:04:00,000 --> 00:04:04,000 Inside of the models directory is where I'll put the user file. 32 00:04:09,000 --> 00:04:12,000 Now let's open up the User model. 33 00:04:13,000 --> 00:04:19,000 Let's refer back to the Sequelize documentation to see how we create a model. 34 00:04:19,000 --> 00:04:22,000 It looks like we use the define keyword. 35 00:04:23,000 --> 00:04:26,000 We're not going to use any validations right now. 36 00:04:28,000 --> 00:04:31,000 Since we're storing our model in a separate file, 37 00:04:31,000 --> 00:04:34,000 it looks like we're going to have to use the import method. 38 00:04:34,000 --> 00:04:38,000 Before we create our model, we need to create our database 39 00:04:38,000 --> 00:04:42,000 and also add a table to it. 40 00:04:42,000 --> 00:04:45,000 I'm going to use Sequel Pro in order to do that. 41 00:04:45,000 --> 00:04:48,000 However, that's not completely necessary. 42 00:04:53,000 --> 00:04:57,000 Now we're going to create our users table. 43 00:05:06,000 --> 00:05:10,000 We're only going to save a few attributes that we get back from Facebook. 44 00:05:10,000 --> 00:05:17,000 For right now I'll just save the Facebook ID, the first name, last name, and email. 45 00:05:32,000 --> 00:05:38,000 In a real application, you would probably want to use an unsigned integer for the Facebook ID. 46 00:05:38,000 --> 00:05:44,000 However, since this is just an example, using a varchar is going to be a lot easier. 47 00:05:44,000 --> 00:05:49,000 Now that we've got our database set up, let's go ahead and create our model. 48 00:05:49,000 --> 00:05:56,000 Since our User model is in a separate file, we're going to have to export that information. 49 00:06:04,000 --> 00:06:07,000 Now let's refer back to the documentation. 50 00:06:07,000 --> 00:06:11,000 It looks like we have to give it a model and then say the different data types. 51 00:06:24,000 --> 00:06:29,000 Here we'll enter all of the information we put in the database. 52 00:06:46,000 --> 00:06:51,000 We're going to want to save certain information that we get back from Facebook. 53 00:06:51,000 --> 00:06:55,000 We'll do this using a custom method inside of our User model. 54 00:06:55,000 --> 00:06:58,000 If we look back at the documentation in Sequelize, 55 00:06:58,000 --> 00:07:03,000 we can see that we can define class methods and instance methods. 56 00:07:03,000 --> 00:07:09,000 We'll go ahead and define a class method called findOrCreateFromMetadata. 57 00:07:09,000 --> 00:07:13,000 What this will do is save the metadata from Facebook. 58 00:07:13,000 --> 00:07:17,000 Or if a user with the Facebook ID already exists, 59 00:07:17,000 --> 00:07:20,000 it will return that user. 60 00:07:20,000 --> 00:07:25,000 This way we won't duplicate information inside of the database. 61 00:07:35,000 --> 00:07:38,000 First, we'll look up to see if the Facebook ID exists. 62 00:07:53,000 --> 00:07:59,000 If the query is successful, we'll store that information inside of a user object. 63 00:07:59,000 --> 00:08:05,000 However, this might not actually exist inside of the database. 64 00:08:05,000 --> 00:08:11,000 The success callback defines whether or not the query was successful. 65 00:08:11,000 --> 00:08:16,000 So if the user doesn't exist, we'll build and save it. 66 00:08:17,000 --> 00:08:23,000 At this point we're going to need access to the User model. 67 00:08:23,000 --> 00:08:28,000 We can't call this.build in order to create our user 68 00:08:28,000 --> 00:08:32,000 because this now refers to the success callback. 69 00:08:32,000 --> 00:08:37,000 So what we'll do is define a variable called model up here 70 00:08:37,000 --> 00:08:41,000 that will have the binding of the User model, 71 00:08:45,000 --> 00:08:48,000 and then we change the reference over in our build function. 72 00:08:48,000 --> 00:08:53,000 Now we'll go ahead and assign the metadata to our different database attributes. 73 00:09:17,000 --> 00:09:20,000 Once we've built the model, we'll save it. 74 00:09:22,000 --> 00:09:32,000 And if it's successful, we'll assign that again to a user object and run the callback. 75 00:09:38,000 --> 00:09:45,000 If it fails, we'll go ahead and log the error 76 00:09:45,000 --> 00:09:49,000 and we'll run the callback with an error and no object. 77 00:09:55,000 --> 00:09:59,000 Now, that's what happens if we don't have a user in the database. 78 00:09:59,000 --> 00:10:02,000 If we do, the user should be returned, 79 00:10:02,000 --> 00:10:09,000 so we'll just run the callback and send in that user object. 80 00:10:09,000 --> 00:10:11,000 And finally, we need to tell Node what to do 81 00:10:11,000 --> 00:10:15,000 in case there's an error when querying the database. 82 00:10:22,000 --> 00:10:24,000 That looks good for now. 83 00:10:24,000 --> 00:10:29,000 Let's go ahead back to our application.coffee. 84 00:10:29,000 --> 00:10:34,000 What we have to do is import the User model we just created. 85 00:10:47,000 --> 00:10:51,000 Now let's scroll down to our authentication portion. 86 00:10:51,000 --> 00:10:55,000 Instead of just rendering a template saying that we've authenticated, 87 00:10:55,000 --> 00:10:59,000 what we'll do is call our findOrCreateFromMetadata 88 00:10:59,000 --> 00:11:04,000 and send in the body of the Facebook response. 89 00:11:11,000 --> 00:11:16,000 We also have to send in our error and object callbacks. 90 00:11:23,000 --> 00:11:26,000 So let's see if the user exists. 91 00:11:34,000 --> 00:11:40,000 In the case that the user does exist, we'll set a user ID session variable 92 00:11:40,000 --> 00:11:46,000 and redirect to an endpoint called /me. 93 00:11:50,000 --> 00:11:53,000 We haven't made that endpoint yet, but we will. 94 00:12:02,000 --> 00:12:08,000 For now, if the user doesn't exist, we'll just redirect them to the homepage. 95 00:12:11,000 --> 00:12:15,000 Finally, we'll create our /me endpoint. 96 00:12:20,000 --> 00:12:26,000 First, we'll check to see if there's a user ID key inside of the session. 97 00:12:30,000 --> 00:12:37,000 If there is a user, we'll go ahead and create a User.findById method. 98 00:12:58,000 --> 00:13:02,000 You'll notice that we're rendering this me.eco template 99 00:13:02,000 --> 00:13:05,000 in the event that we find the user. 100 00:13:05,000 --> 00:13:07,000 Let's go ahead and create that. 101 00:13:11,000 --> 00:13:16,000 It looks like we have an error on line 13 of our application file. 102 00:13:16,000 --> 00:13:19,000 Let's go ahead and see what's going on. 103 00:13:19,000 --> 00:13:25,000 It seems like I've messed up the indentation here when defining our Sequelize variables. 104 00:13:34,000 --> 00:13:37,000 Let's go ahead and try and run it again. 105 00:13:37,000 --> 00:13:41,000 So we load up our homepage and click Log In. 106 00:13:41,000 --> 00:13:47,000 I'm already logged in to Facebook, so it won't ask me to authorize the application. 107 00:13:48,000 --> 00:13:51,000 It seems our server died. Let's see what happened. 108 00:13:51,000 --> 00:13:55,000 It says we have no method findOrCreateFromMetadata. 109 00:13:55,000 --> 00:14:00,000 That's going to be in the User model. Let's open that up and see what's going on. 110 00:14:01,000 --> 00:14:06,000 It looks like I forgot the classMethods argument. 111 00:14:19,000 --> 00:14:21,000 Let's try it again. 112 00:14:25,000 --> 00:14:30,000 It looks like we have another error saying that we have no method findById. 113 00:14:30,000 --> 00:14:34,000 A quick look in the User model shows that I misspelled it. 114 00:14:34,000 --> 00:14:37,000 Let's correct it and try again. 115 00:14:40,000 --> 00:14:45,000 It would seem once more that we're indented just a bit too much. 116 00:14:45,000 --> 00:14:49,000 These are some of the quirks of CoffeeScript that you have to get used to. 117 00:14:51,000 --> 00:14:54,000 Here I have another typo. 118 00:14:57,000 --> 00:15:00,000 And we finally got that to work. 119 00:15:00,000 --> 00:15:03,000 Let's go ahead and look inside of our database. 120 00:15:05,000 --> 00:15:08,000 All of our content is there.