1 00:00:00,410 --> 00:00:05,040 We've set our new wiki page form up to submit via an HTTP POST request, but 2 00:00:05,040 --> 00:00:08,170 we're getting the error Sinatra doesn't know this ditty. 3 00:00:08,170 --> 00:00:12,290 The problem is that we need to set up a Sinatra route to handle POST requests. 4 00:00:12,290 --> 00:00:16,180 Down here Sinatra provides us with a sample route to get us started, 5 00:00:16,180 --> 00:00:17,890 post to the /create path. 6 00:00:18,960 --> 00:00:21,760 Let's go back in our main app code and add a post route there. 7 00:00:23,670 --> 00:00:28,930 Just as you used Sinatra's GET method to set up routes to handle HTTP GET requests, 8 00:00:28,930 --> 00:00:33,750 you use Sinatra's POST method to set up routes for HTTP POST requests. 9 00:00:34,840 --> 00:00:37,790 The post method works in much the same way as the get method. 10 00:00:37,790 --> 00:00:38,980 You call the method and 11 00:00:38,980 --> 00:00:44,060 pass of a string with the request path should match /create in this case. 12 00:00:45,180 --> 00:00:48,146 Then you pass it a block that should be called whenever a matching post 13 00:00:48,146 --> 00:00:48,942 request is received. 14 00:00:52,900 --> 00:00:55,580 For now we'll just have the block respond to the browser with a string. 15 00:00:56,960 --> 00:01:06,280 Hello from the post "/create" route! 16 00:01:06,280 --> 00:01:10,140 By the way, you may be remembering how our get new route 17 00:01:10,140 --> 00:01:14,040 conflicted with the URL parameter in the get title route. 18 00:01:14,040 --> 00:01:16,580 You may be wondering if it's okay to define our post 19 00:01:16,580 --> 00:01:19,170 create route down here at the bottom of the file. 20 00:01:19,170 --> 00:01:20,350 There's no need to worry. 21 00:01:20,350 --> 00:01:24,110 None of the get routes will match our post request no matter what the path 22 00:01:24,110 --> 00:01:26,520 is because the request type is different. 23 00:01:26,520 --> 00:01:29,350 We might need to be concerned if there were another post route with 24 00:01:29,350 --> 00:01:30,580 a URL parameter. 25 00:01:30,580 --> 00:01:32,690 But since this is the only post route, 26 00:01:32,690 --> 00:01:35,650 we can define it anywhere in the file we want. 27 00:01:35,650 --> 00:01:37,170 Let's test this new route. 28 00:01:37,170 --> 00:01:39,426 Remember because we made a change to our Ruby code, 29 00:01:39,426 --> 00:01:42,110 we have to restart the server even if it's already running. 30 00:01:46,328 --> 00:01:50,984 Now, I'll visit form to create a new page, fill it out. 31 00:01:59,570 --> 00:02:04,050 And then submit it, which should send a POST request to the /create path. 32 00:02:04,050 --> 00:02:04,900 And in response, 33 00:02:04,900 --> 00:02:09,410 instead of an error, we see our string, Hello from the post "/create" route! 34 00:02:09,410 --> 00:02:11,870 Our route is being mapped successfully. 35 00:02:11,870 --> 00:02:14,690 Displaying placeholder messages is all fine and good, but 36 00:02:14,690 --> 00:02:18,470 we need a route to take our form data and save a new Wiki page for us. 37 00:02:19,520 --> 00:02:22,020 Remember our route to view an individual page which 38 00:02:22,020 --> 00:02:25,090 got the page title from a URL parameter? 39 00:02:25,090 --> 00:02:29,740 That parameter was made available within the route block through the params hash. 40 00:02:29,740 --> 00:02:34,450 Form parameters from POST requests also get placed into the params hash. 41 00:02:34,450 --> 00:02:37,120 We can look at the form parameters by calling the inspect 42 00:02:37,120 --> 00:02:40,540 method on params which converts the hash to a string. 43 00:02:40,540 --> 00:02:43,670 So I'll replace our placeholder text, and 44 00:02:43,670 --> 00:02:48,520 get the parames hash and call the inspect method on it. 45 00:02:48,520 --> 00:02:52,937 Now if we restart the server, and fill out the form. 46 00:02:57,915 --> 00:03:02,700 And submit it, we'll see the title we entered under the title key. 47 00:03:02,700 --> 00:03:04,880 And the content we entered under the content key. 48 00:03:05,950 --> 00:03:07,962 Let's copy this string, and 49 00:03:07,962 --> 00:03:13,125 paste it temporarily in a comment right above our route so we can refer to it. 50 00:03:19,046 --> 00:03:22,120 So remember the save content method we set up previously? 51 00:03:24,130 --> 00:03:26,300 It takes the title string and the content string. 52 00:03:28,230 --> 00:03:30,480 And saves the content to a text file for us. 53 00:03:31,960 --> 00:03:35,777 And now we finally have the title and the content ready to pass to it is input. 54 00:03:38,924 --> 00:03:41,959 We'll call save_content within our route block. 55 00:03:41,959 --> 00:03:47,003 For the title, we'll pass it the value from the title key of the params hash. 56 00:03:51,724 --> 00:03:56,873 And for the content, we'll pass it the value from 57 00:03:56,873 --> 00:04:01,541 the content key, params["content"]. 58 00:04:01,541 --> 00:04:03,173 Let's restart our server again. 59 00:04:07,501 --> 00:04:09,085 We'll visit the new page form. 60 00:04:11,117 --> 00:04:15,830 It's already filled out from our prior submission, and let's submit it again. 61 00:04:15,830 --> 00:04:18,050 We'll see only a blank page in response. 62 00:04:18,050 --> 00:04:21,593 But if we go back to our workspace, refresh our file list, 63 00:04:24,416 --> 00:04:28,388 And look in the pages directory, we'll see a text file with the page 64 00:04:28,388 --> 00:04:33,320 title we entered as its name and the contents we entered as its content. 65 00:04:33,320 --> 00:04:42,285 If we go back to the preview again, fill out the form again, And submit it again, 66 00:04:42,285 --> 00:04:46,960 we'll get another blank page but, we can go back to the workspace, refresh again. 67 00:04:46,960 --> 00:04:51,920 And we'll see another new file based on our form contents. 68 00:04:51,920 --> 00:04:53,650 We're successfully saving our form data. 69 00:04:53,650 --> 00:04:57,040 There is one more detail to take care of. 70 00:04:57,040 --> 00:05:00,610 We don't want the browser to just show a blank page after we submit the form. 71 00:05:00,610 --> 00:05:03,180 So the final thing we'll do is tell the browser to make a GET 72 00:05:03,180 --> 00:05:06,170 request to show the new page after it's saved. 73 00:05:06,170 --> 00:05:09,890 To do that will add a call to the redirect method at the end of a route block. 74 00:05:10,910 --> 00:05:15,330 The redirect method tells Sinatra to send a redirect response to the browser, 75 00:05:15,330 --> 00:05:20,160 redirects cause the browser to send the GET requests for a particular URL or path. 76 00:05:20,160 --> 00:05:23,470 Whatever string you pass to the redirect method, that's the URL or 77 00:05:23,470 --> 00:05:26,220 path the browser will be redirected to. 78 00:05:26,220 --> 00:05:30,200 The path for the new page will consist of a slash followed by the page title. 79 00:05:30,200 --> 00:05:33,470 So we'll use the title parameter to construct the path for the redirect. 80 00:05:33,470 --> 00:05:38,463 So we'll start the string with a slash and then interpolate the title parameter, 81 00:05:44,525 --> 00:05:45,425 Into the string. 82 00:05:45,425 --> 00:05:48,030 Our route should be complete now, so 83 00:05:48,030 --> 00:05:50,130 we shouldn't need the reference comment anymore. 84 00:05:50,130 --> 00:05:50,920 Let's delete that. 85 00:05:52,050 --> 00:05:53,340 Let's restart the server again. 86 00:05:55,890 --> 00:05:57,640 Now we can go back to the new page form. 87 00:05:58,930 --> 00:06:00,228 Submit a new page. 88 00:06:03,348 --> 00:06:05,870 And once the page is saved we'll be redirected to view it. 89 00:06:07,610 --> 00:06:11,460 This works fine until we try to submit a new page that has a space in the title. 90 00:06:12,590 --> 00:06:14,630 At that point the page will seem to lock up and 91 00:06:14,630 --> 00:06:18,340 may eventually return a 502 bad gateway message. 92 00:06:18,340 --> 00:06:21,180 We've seen that when Sinatra starts up it prints a bunch of debug 93 00:06:21,180 --> 00:06:23,070 messages to the terminal. 94 00:06:23,070 --> 00:06:25,440 If Sinatra encounters any errors while it's running, 95 00:06:25,440 --> 00:06:28,480 the error messages get logged in the terminal too. 96 00:06:28,480 --> 00:06:32,290 Let's go back to our workspace and look at the Sinatra log messages in the console. 97 00:06:33,290 --> 00:06:35,371 We'll scroll up until we find the problem. 98 00:06:38,268 --> 00:06:40,740 InvalidURIError. 99 00:06:40,740 --> 00:06:43,110 URI basically means the same thing as URL. 100 00:06:44,140 --> 00:06:47,590 We'll also see the URL that the create route tried to redirect us to. 101 00:06:49,900 --> 00:06:53,470 The problem is that spaces aren't a valid character within a URL, 102 00:06:53,470 --> 00:06:55,220 they need to be encoded. 103 00:06:55,220 --> 00:06:57,916 If you type a space into your browser address bar or 104 00:06:57,916 --> 00:07:00,364 click on a link with a space, it'll be okay. 105 00:07:00,364 --> 00:07:06,050 Let's try this here, Alena Holligan, note the space in there. 106 00:07:07,330 --> 00:07:10,568 Your browser encodes the space characters when it sends the request. 107 00:07:10,568 --> 00:07:13,990 But when we're sending a redirect back to the browser, 108 00:07:13,990 --> 00:07:17,090 we need to encode the URL ourselves. 109 00:07:17,090 --> 00:07:19,530 We can do that with the URI module. 110 00:07:19,530 --> 00:07:21,220 It's part of the Ruby standard library, 111 00:07:21,220 --> 00:07:24,450 which means it's included with every Ruby distribution. 112 00:07:24,450 --> 00:07:29,200 The URI escape method can escape that is, encode the redirect path for us. 113 00:07:30,350 --> 00:07:34,190 First we're going to need to load the URI library at the top of the file, 114 00:07:34,190 --> 00:07:39,470 right here and to require "sinatra" we'll type, require 'uri". 115 00:07:39,470 --> 00:07:41,295 Note that it's named uri, 116 00:07:41,295 --> 00:07:45,190 not URL, if you type URL here, the library will fail to load. 117 00:07:47,140 --> 00:07:52,510 Then we'll take our redirect path and pass it exactly as it is URI.escape. 118 00:07:52,510 --> 00:07:56,850 The return value of URI.escape 119 00:07:56,850 --> 00:08:00,560 will be the same path string except that if it contains any bases or 120 00:08:00,560 --> 00:08:03,720 other invalid characters, they'll be encoded so the path is valid. 121 00:08:05,420 --> 00:08:06,710 Now let's restart our server. 122 00:08:08,770 --> 00:08:12,090 And now I'll try submitting a page with a space in the title again. 123 00:08:12,090 --> 00:08:15,710 We've already got the form filled out, let's click Submit. 124 00:08:15,710 --> 00:08:18,410 And this time we're successfully redirected to the new page. 125 00:08:18,410 --> 00:08:21,493 And there are no errors from Sinatra logged in the console. 126 00:08:23,860 --> 00:08:26,710 Our users can create new pages now, nice work. 127 00:08:26,710 --> 00:08:29,810 We set up one Sinatra route that lets users send GET requests for 128 00:08:29,810 --> 00:08:31,830 a new HTML form. 129 00:08:31,830 --> 00:08:35,740 Then we set up a second route that accepts POST requests with the form data and 130 00:08:35,740 --> 00:08:36,680 saves it to a file. 131 00:08:38,460 --> 00:08:41,140 We've shown you techniques to load existing page data and 132 00:08:41,140 --> 00:08:42,760 to save new page data. 133 00:08:42,760 --> 00:08:43,565 In the next stage, 134 00:08:43,565 --> 00:08:47,067 we'll combine those abilities to let users edit existing pages.