1 00:00:00,000 --> 00:00:02,000 [?music?] 2 00:00:02,000 --> 00:00:05,000 [Master Class: Designer and Developer Workflow: Associating Jobs and Users] 3 00:00:05,000 --> 00:00:08,000 [Jim Hoskins] So let's take a look at the application we have so far 4 00:00:08,000 --> 00:00:10,000 and see what the next steps are for us. 5 00:00:10,000 --> 00:00:16,000 Right now, we have the ability to list jobs and view specific jobs 6 00:00:16,000 --> 00:00:24,000 and we can go back and we have the ability to register as well as sign in. 7 00:00:24,000 --> 00:00:26,000 When we go ahead and try this out-- 8 00:00:26,000 --> 00:00:29,000 let's see if I can remember my password-- 9 00:00:29,000 --> 00:00:33,000 and we have the ability to sign in here, so we have an authentication system 10 00:00:33,000 --> 00:00:38,000 and the ability in our application to see if somebody is signed in or signed out. 11 00:00:38,000 --> 00:00:41,000 And of course, we can just go ahead and sign out again. 12 00:00:41,000 --> 00:00:44,000 So the authentication system is a great first step, 13 00:00:44,000 --> 00:00:49,000 but it's really a means to an end and that end is to make sure 14 00:00:49,000 --> 00:00:52,000 that people can manage the job that they create 15 00:00:52,000 --> 00:00:57,000 as well as only people who are registered users and logged in can create accounts 16 00:00:57,000 --> 00:01:01,000 and to make sure that nobody can edit somebody else's job. 17 00:01:01,000 --> 00:01:05,000 So we have an authentication system in place, but now we need to worry about authorization 18 00:01:05,000 --> 00:01:10,000 and making sure that the right people can do the right tasks on our site. 19 00:01:10,000 --> 00:01:14,000 So since one of the main goals is to make sure that somebody can only edit 20 00:01:14,000 --> 00:01:19,000 the jobs that they created, we need to have some way of associating a user 21 00:01:19,000 --> 00:01:21,000 with the job that they've created. 22 00:01:21,000 --> 00:01:23,000 That way, when somebody tries to edit it, 23 00:01:23,000 --> 00:01:28,000 we can compare the person who's trying to do the edit with the person who created the job. 24 00:01:28,000 --> 00:01:32,000 So what we're going to want to do is associate a user with a job, 25 00:01:32,000 --> 00:01:36,000 so Rails offers association helpers, which make this pretty easy to do. 26 00:01:36,000 --> 00:01:40,000 Basically, all we need to do is add a field to the job 27 00:01:40,000 --> 00:01:43,000 which will hold the ID of the user who created it 28 00:01:43,000 --> 00:01:47,000 and by using conventions and built-in association methods, 29 00:01:47,000 --> 00:01:53,000 we can have a lot of easy ways to ensure that a job is always associated with a user. 30 00:01:53,000 --> 00:01:56,000 So the first step for this is to add the actual field, and for that, 31 00:01:56,000 --> 00:01:59,000 we'll go ahead and create a migration in Rails. 32 00:01:59,000 --> 00:02:04,000 A database migration is simply our way of describing to Rails 33 00:02:04,000 --> 00:02:07,000 how our database is changing over the development cycle, 34 00:02:07,000 --> 00:02:11,000 so since we want to add a field to a table, 35 00:02:11,000 --> 00:02:16,000 we want to specify that as we move forward, we want to add this column to the table, 36 00:02:16,000 --> 00:02:19,000 and if we wanted to go back a version, it would also explain how to go back 37 00:02:19,000 --> 00:02:22,000 to a previous version of the database. 38 00:02:22,000 --> 00:02:25,000 We'll go ahead generate a new migration, and to do that, 39 00:02:25,000 --> 00:02:30,000 we'll do $rails generate migration 40 00:02:30,000 --> 00:02:32,000 and I'm going to give this migration a name 41 00:02:32,000 --> 00:02:37,000 and we want to add a user_id column to the jobs table, 42 00:02:37,000 --> 00:02:41,000 and the user id column is where we'll store the user_id 43 00:02:41,000 --> 00:02:46,000 of the person who is associated with that job--the owner of that job. 44 00:02:46,000 --> 00:02:50,000 So there's actually a special naming convention we can use that will actually generate 45 00:02:50,000 --> 00:02:52,000 pretty much most of our migration for us, 46 00:02:52,000 --> 00:03:01,000 so I'm going to call this add_user_id_to_jobs 47 00:03:01,000 --> 00:03:06,000 and it's really the add to jobs part that is triggering the special behavior. 48 00:03:06,000 --> 00:03:10,000 Rails now knows that we are adding a field to a job 49 00:03:10,000 --> 00:03:19,000 so we can actually specify that field after it by typing in user_id:integer. 50 00:03:19,000 --> 00:03:22,000 So now, hopefully, instead of creating an empty migration, 51 00:03:22,000 --> 00:03:27,000 we should get a migration that already has what we need to add this one field to the table. 52 00:03:27,000 --> 00:03:31,000 Now, hopefully, instead of creating an empty migration, we'll create a migration 53 00:03:31,000 --> 00:03:38,000 that has the code we need to add this column to the table. 54 00:03:38,000 --> 00:03:42,000 So now we have a new file in db/migrate that's called _add_user_id_to_jobs 55 00:03:42,000 --> 00:03:46,000 so let's go ahead and take a look at it. 56 00:03:46,000 --> 00:03:49,000 Just open up db/migrate, 57 00:03:49,000 --> 00:03:52,000 grab this last one. 58 00:03:52,000 --> 00:03:54,000 We can see that the generator actually understood what we wanted. 59 00:03:54,000 --> 00:03:58,000 We're adding a column to the jobs table called user_id 60 00:03:58,000 --> 00:04:02,000 and it's of types integer, and if we wanted to roll back this change, all we need to do 61 00:04:02,000 --> 00:04:06,000 is remove the column user_id from jobs. 62 00:04:06,000 --> 00:04:09,000 So let's go ahead and actually migrate our database. 63 00:04:09,000 --> 00:04:12,000 If we want to take a look at what the schema looks like right now, 64 00:04:12,000 --> 00:04:17,000 we can see that the jobs table has title, description, company_name, 65 00:04:17,000 --> 00:04:19,000 created_at and updated_at. 66 00:04:19,000 --> 00:04:27,000 When we go ahead and run this migration by typing in $rake.db:migrate, 67 00:04:27,000 --> 00:04:29,000 we'll see it has added the column, 68 00:04:29,000 --> 00:04:34,000 and if we go back to our schema.rb here, we can see that the table jobs now has an integer 69 00:04:34,000 --> 00:04:37,000 user_id column. 70 00:04:37,000 --> 00:04:41,000 So now we have a user_id column in our jobs field, so what we want to do now 71 00:04:41,000 --> 00:04:46,000 is create the associations between jobs and users so we can use it programmatically 72 00:04:46,000 --> 00:04:49,000 in our controllers and views. 73 00:04:49,000 --> 00:04:55,000 So the first thing we'll do is open up app/models/job, 74 00:04:55,000 --> 00:05:01,000 and so if the job table contains a user_id field, the relationship between job and users 75 00:05:01,000 --> 00:05:10,000 is that job belongs to a user and that's because the user_id is marked on the job's actual table. 76 00:05:10,000 --> 00:05:16,000 So in order to do this, we will write belongs_to 77 00:05:16,000 --> 00:05:20,000 and all we need to do is say :user 78 00:05:20,000 --> 00:05:24,000 and what this does is creates a user method on the job 79 00:05:24,000 --> 00:05:28,000 which we can use to actually assign or retrieve instances of the user class 80 00:05:28,000 --> 00:05:34,000 which will be based on the user_id column in our database. 81 00:05:34,000 --> 00:05:37,000 Since we called that column user_id 82 00:05:37,000 --> 00:05:41,000 and the class that we're associating with is called user, 83 00:05:41,000 --> 00:05:46,000 we don't have to specify anything more than this because Rails will infer all of those things 84 00:05:46,000 --> 00:05:50,000 based on its defaults, so we'll save this. 85 00:05:50,000 --> 00:05:52,000 So now we've associated user to job, 86 00:05:52,000 --> 00:05:57,000 but let's go ahead and do the inverse, associate jobs to user. 87 00:05:57,000 --> 00:06:06,000 So we'll open up user.rb and I'll write has_many: jobs. 88 00:06:06,000 --> 00:06:09,000 And by default, Rails will assume that there is a job model 89 00:06:09,000 --> 00:06:12,000 and that job model has a user_id column in it 90 00:06:12,000 --> 00:06:16,000 that associates to this class's primary key, which it does. 91 00:06:16,000 --> 00:06:21,000 So since we're going with the Rails assumptions, we have to write very little code 92 00:06:21,000 --> 00:06:23,000 to associate it. 93 00:06:23,000 --> 00:06:27,000 So now if we have a user instance, we can call jobs, which would return an array of all the jobs 94 00:06:27,000 --> 00:06:32,000 that are associated with that user, and that will come in handy later. 95 00:06:32,000 --> 00:06:37,000 So let's go into the console and see how this works. 96 00:06:37,000 --> 00:06:42,000 I'll go ahead and type $rails c or $rails console 97 00:06:42,000 --> 00:06:47,000 and let's grab the first user by just typing in User.first 98 00:06:47,000 --> 00:06:51,000 and I'll assign it to the lowercase user variable. 99 00:06:51,000 --> 00:06:55,000 So here we have the user jim@carsonified, the one that I have been using, 100 00:06:55,000 --> 00:07:00,000 and let's grab the first job and assign it to a job here 101 00:07:00,000 --> 00:07:05,000 and we'll just grab Job.first. 102 00:07:05,000 --> 00:07:11,000 So now we have Ice Cream Tester and my user account in variables here, 103 00:07:11,000 --> 00:07:13,000 both user and job. 104 00:07:13,000 --> 00:07:22,000 So if I wanted to say job.user = user, our local user variable here, 105 00:07:22,000 --> 00:07:27,000 we can assign it just like that and what Rails does under the covers 106 00:07:27,000 --> 00:07:31,000 is assign this job's user_id to the user instances idea 107 00:07:31,000 --> 00:07:34,000 and all we need to do is job.save. 108 00:07:34,000 --> 00:07:40,000 And if we wanted to say job.user_id, for instance, we'll see it's 1. 109 00:07:40,000 --> 00:07:44,000 So now, any time that we grab this job, we can simply type in job.user 110 00:07:44,000 --> 00:07:51,000 and Rails will go into the database and instantiate the user based on the user_id. 111 00:07:51,000 --> 00:07:55,000 And this is pretty handy because it's easier to work with the actual model instances 112 00:07:55,000 --> 00:08:00,000 than worry about foreign keys and primary keys and all of that. 113 00:08:00,000 --> 00:08:04,000 So this will be pretty good, and let's see how we can integrate this into our application.