1 00:00:16,920 --> 00:00:19,920 ANDREW WARNER: Welcome. I an Andrew Warner. 2 00:00:19,930 --> 00:00:22,169 I am the director of engineering at 3 00:00:22,169 --> 00:00:24,820 RapGenius dot com. You can follow me 4 00:00:24,820 --> 00:00:28,089 on Twitter at wwarner. And you can also 5 00:00:28,089 --> 00:00:30,710 follow RapGenius on Twitter at RapGenius. 6 00:00:30,710 --> 00:00:32,598 So Tweet at me during the presentation, 7 00:00:32,598 --> 00:00:34,690 after the presentation, tomorrow. 8 00:00:34,690 --> 00:00:38,210 Whatever. I'm down. I will respond to your stuff. 9 00:00:38,210 --> 00:00:40,649 So, this is really exciting for me. This is 10 00:00:40,649 --> 00:00:43,890 my first RailsConf speaking. And so, you know, I'm 11 00:00:43,890 --> 00:00:47,970 super excited to be here. Come on. Little round 12 00:00:47,970 --> 00:00:50,470 of applause. Yeah. Yeah. 13 00:00:50,470 --> 00:00:53,420 This is very exciting for me, not just because 14 00:00:53,420 --> 00:00:55,680 I'm speaking, but also because you all, you know, 15 00:00:55,680 --> 00:00:57,689 this is a pretty full room. You all chose 16 00:00:57,689 --> 00:00:59,559 my talk over the other two talks! This is, 17 00:00:59,559 --> 00:01:01,460 you know, it makes me feel good. It also 18 00:01:01,460 --> 00:01:03,559 is crazy, because, how do you even know what 19 00:01:03,559 --> 00:01:05,790 I'm gonna be talking about? I had some summary 20 00:01:05,790 --> 00:01:07,540 that's kind of vague. Like, maybe I'm gonna say 21 00:01:07,540 --> 00:01:09,360 some stuff, but, you know, maybe I'm gonna change 22 00:01:09,360 --> 00:01:10,740 it a little bit. Now I've got this slide 23 00:01:10,740 --> 00:01:12,500 on the screen that says Rails Holy Grail. Who 24 00:01:12,500 --> 00:01:14,890 knows what that even means? So, you know, I'm 25 00:01:14,890 --> 00:01:17,260 excited that you chose me even besides all this 26 00:01:17,260 --> 00:01:17,560 stuff. 27 00:01:17,560 --> 00:01:20,890 So, you know, I'm gonna be talking today about 28 00:01:20,890 --> 00:01:22,500 the Rails Holy Grail. I'm a little bit disappointed 29 00:01:22,500 --> 00:01:24,940 that DHH kind of stole my thunder with his 30 00:01:24,940 --> 00:01:27,409 Holy Grail slide. But, you know, I, I still, 31 00:01:27,409 --> 00:01:29,470 I'm gonna use it. I couldn't find another replacement 32 00:01:29,470 --> 00:01:31,530 Holy Grail slide in the meantime. 33 00:01:31,530 --> 00:01:33,890 So, I guess, what am I gonna be telling 34 00:01:33,890 --> 00:01:36,530 you about? Well, first, I'm gonna be talking to 35 00:01:36,530 --> 00:01:38,500 you about what the Holy Grail is. So what 36 00:01:38,500 --> 00:01:40,810 I mean when I say the Holy Grail. I'm 37 00:01:40,810 --> 00:01:43,140 gonna be showing you some existing Rails solutions that 38 00:01:43,140 --> 00:01:45,920 kind of get us close to this. I'm going 39 00:01:45,920 --> 00:01:47,810 to be offering up a new solution for your 40 00:01:47,810 --> 00:01:51,760 consideration today. And I'm gonna show you what else 41 00:01:51,760 --> 00:01:54,760 this new solution gets us. 42 00:01:54,760 --> 00:01:58,710 So, first off, what is the Holy Grail of 43 00:01:58,710 --> 00:02:01,080 the web? This background is like the song Holy 44 00:02:01,080 --> 00:02:04,090 Grail by Jay-Z. I don't know. So, the Holy 45 00:02:04,090 --> 00:02:06,010 Grail of the web, what I actually mean when 46 00:02:06,010 --> 00:02:08,860 I say Holy Grail, is the best possible user 47 00:02:08,860 --> 00:02:14,090 experience combined with the best possible developer experience. So 48 00:02:14,090 --> 00:02:15,840 it should be very easy for me to rapidly 49 00:02:15,840 --> 00:02:19,319 develop an application, as a developer, that is also 50 00:02:19,319 --> 00:02:22,750 easy to use for a user. 51 00:02:22,750 --> 00:02:25,440 And so what is the best possible user experience? 52 00:02:25,440 --> 00:02:28,730 Well, I'm talking about sort of a, a single-page 53 00:02:28,730 --> 00:02:31,230 app thick client feel. So you shouldn't have to 54 00:02:31,230 --> 00:02:34,790 reload the entire page every time you, every time 55 00:02:34,790 --> 00:02:37,280 the user actually clicks on a link. So in 56 00:02:37,280 --> 00:02:39,330 2004, when Rails came out, it was really great 57 00:02:39,330 --> 00:02:42,440 because it allowed you to create, very quickly, websites 58 00:02:42,440 --> 00:02:44,510 which were kind of a thin client, where every 59 00:02:44,510 --> 00:02:46,349 single click reloaded the whole page. 60 00:02:46,349 --> 00:02:48,459 And this was revolutionary. Before that, you know, it 61 00:02:48,459 --> 00:02:51,260 was really difficult to make a site rapidly. And 62 00:02:51,260 --> 00:02:54,190 around the same time, actually, Google released this Gmail 63 00:02:54,190 --> 00:02:55,560 thing. Kind of hard to see the screenshot, but 64 00:02:55,560 --> 00:02:58,630 I think you're all familiar with what Gmail actually 65 00:02:58,630 --> 00:03:01,959 is. Gmail was this single-page app where every single 66 00:03:01,959 --> 00:03:04,700 click actually loaded right on the same page that 67 00:03:04,700 --> 00:03:06,610 you were on whatever you content you wanted to 68 00:03:06,610 --> 00:03:08,000 see as the user. You didn't have to wait 69 00:03:08,000 --> 00:03:10,650 for your whole browser to refresh. This is pretty 70 00:03:10,650 --> 00:03:13,090 good. So it's just no full page reloads at 71 00:03:13,090 --> 00:03:15,069 all. This is the best experience for the user, 72 00:03:15,069 --> 00:03:17,239 and it should sort of feel like a desktop 73 00:03:17,239 --> 00:03:19,840 app or a mobile app in terms of the 74 00:03:19,840 --> 00:03:21,450 native feel. 75 00:03:21,450 --> 00:03:24,610 The best developer experience is a little bit different. 76 00:03:24,610 --> 00:03:26,879 So, you should be able to use a developer-friendly 77 00:03:26,879 --> 00:03:28,650 framework. You should be able to rapidly develop something. 78 00:03:28,650 --> 00:03:31,860 You shouldn't have to reinvent the wheel. Easy things 79 00:03:31,860 --> 00:03:34,349 should be easy. So, Ruby on Rails is one 80 00:03:34,349 --> 00:03:36,030 of these frameworks. You might have heard of this. 81 00:03:36,030 --> 00:03:39,120 Kind of why we're here today. So you should 82 00:03:39,120 --> 00:03:41,250 be able to use a developer-friendly framework. 83 00:03:41,250 --> 00:03:43,720 You should be DRY. You shouldn't have to repeat 84 00:03:43,720 --> 00:03:46,680 yourself. D-R-Y. Don't Repeat Yourself. But actually, what I 85 00:03:46,680 --> 00:03:49,160 mean here is more like DRV. So what is 86 00:03:49,160 --> 00:03:52,129 DRV? Well, I mean, you shouldn't have to repeat 87 00:03:52,129 --> 00:03:53,690 views. You shouldn't have to write one set of 88 00:03:53,690 --> 00:03:56,209 views that lives on the client's browser and one 89 00:03:56,209 --> 00:03:58,810 set of the views that lives on your web 90 00:03:58,810 --> 00:04:00,440 server. 91 00:04:00,440 --> 00:04:02,540 You should be writing mostly one language. At least, 92 00:04:02,540 --> 00:04:04,230 in so far as views are concerned. So you 93 00:04:04,230 --> 00:04:06,849 shouldn't have to context switch. Context switching is very 94 00:04:06,849 --> 00:04:09,550 expensive. Sort of switching from Ruby and Rails to 95 00:04:09,550 --> 00:04:13,069 JavaScript. This is difficult for us, as developers. 96 00:04:13,069 --> 00:04:15,090 And your website should be SEO friendly. So I 97 00:04:15,090 --> 00:04:17,810 guess this part really applies to content sites. So 98 00:04:17,810 --> 00:04:21,459 I work at RapGenius dot com. Content and SEO 99 00:04:21,459 --> 00:04:23,870 friendliness is extremely important for us. We lost a 100 00:04:23,870 --> 00:04:26,300 bunch of traffic when we actually got banned from 101 00:04:26,300 --> 00:04:28,750 Google for a little while. They showed us exactly 102 00:04:28,750 --> 00:04:31,720 how important SEO was. So your site should be 103 00:04:31,720 --> 00:04:35,280 able to show a crawler, a search engine crawler. 104 00:04:35,280 --> 00:04:37,620 HTML that it can index and than make available 105 00:04:37,620 --> 00:04:39,080 for users' searching. 106 00:04:39,080 --> 00:04:42,090 So so what is the closest thing to this 107 00:04:42,090 --> 00:04:44,560 Holy Grail today? 108 00:04:44,560 --> 00:04:49,620 Well, it's kind of the node.js. There's a node.js 109 00:04:49,620 --> 00:04:50,960 solution that I think is the best thing. Come 110 00:04:50,960 --> 00:04:54,930 on, boo node.js! Give me some boos. 111 00:04:54,930 --> 00:04:57,400 So there's this Airbnb Rendr framework, right. So this 112 00:04:57,400 --> 00:05:00,490 says render your backbone JS apps on the client 113 00:05:00,490 --> 00:05:03,380 and on the server using node.js. So this framework 114 00:05:03,380 --> 00:05:05,880 is, you know, pretty easy to use. You write 115 00:05:05,880 --> 00:05:09,530 your backbone JS client-side app and the client can 116 00:05:09,530 --> 00:05:11,380 sort of incrementally update the page and this sort 117 00:05:11,380 --> 00:05:14,680 of Gmail-like experience. And then the server can also 118 00:05:14,680 --> 00:05:18,970 render full HTML pages for arbitrarily deep links. So 119 00:05:18,970 --> 00:05:20,820 the user can still see a full HTML page 120 00:05:20,820 --> 00:05:23,500 if they get deep-linked, and a web browser, or 121 00:05:23,500 --> 00:05:25,750 sorry, a web crawler for a search engine can 122 00:05:25,750 --> 00:05:27,610 also see HTML. So this, I think, is the 123 00:05:27,610 --> 00:05:29,940 best solution right there. Right, out there today. 124 00:05:29,940 --> 00:05:32,190 And here, I've actually built like a little demo 125 00:05:32,190 --> 00:05:33,750 app using render to show you how cool it 126 00:05:33,750 --> 00:05:35,880 is. So this is a little bit washed out. 127 00:05:35,880 --> 00:05:37,949 But, this is sort of a mini version of 128 00:05:37,949 --> 00:05:41,270 our site RapGenius. It's, so RapGenius allows you to 129 00:05:41,270 --> 00:05:45,169 view documents and read documents and also read inline 130 00:05:45,169 --> 00:05:48,040 annotations on those documents. And the annotations are meant 131 00:05:48,040 --> 00:05:52,830 to provide context and also explanation, if something's complicated, 132 00:05:52,830 --> 00:05:54,370 and just add to the text. 133 00:05:54,370 --> 00:05:56,970 So here I've built RailsGenius, which allows you to 134 00:05:56,970 --> 00:06:01,169 add context to, like, Rails talk abstracts. So this 135 00:06:01,169 --> 00:06:04,220 is my talk. And I've added some inline annotations 136 00:06:04,220 --> 00:06:05,370 here, and the, the point I'm trying to make 137 00:06:05,370 --> 00:06:06,970 is that we should be able to, when I 138 00:06:06,970 --> 00:06:09,360 click this link, to add views, which is actually 139 00:06:09,360 --> 00:06:11,780 an annotation, this shouldn't refresh the whole page. It 140 00:06:11,780 --> 00:06:13,530 should just load-in the part of the page that 141 00:06:13,530 --> 00:06:15,759 changed. Which is a much better experience for the 142 00:06:15,759 --> 00:06:16,250 user. 143 00:06:16,250 --> 00:06:17,810 So if I actually click on this, it just 144 00:06:17,810 --> 00:06:19,650 loads that part of the page. You know, this 145 00:06:19,650 --> 00:06:21,430 is something that, you know, might be familiar to 146 00:06:21,430 --> 00:06:23,539 you from using apps, but it's, it's kind of 147 00:06:23,539 --> 00:06:25,090 hard to like do this out of the box 148 00:06:25,090 --> 00:06:27,240 in Rails. And, you know, also you should be 149 00:06:27,240 --> 00:06:29,289 able to like edit it right there and that 150 00:06:29,289 --> 00:06:31,570 should just snap in the edit view, et cetera. 151 00:06:31,570 --> 00:06:33,520 And this should not be too, too difficult to 152 00:06:33,520 --> 00:06:36,710 build. Looks like I lost my internet connection. There 153 00:06:36,710 --> 00:06:38,220 we go. 154 00:06:38,220 --> 00:06:40,970 So this kind of stacks up pretty well. It's 155 00:06:40,970 --> 00:06:44,300 DRY. We have one set of views. It's SEO-friendly. 156 00:06:44,300 --> 00:06:48,280 You know, we can serve HTML the crawlers. It's 157 00:06:48,280 --> 00:06:51,759 a thick-client feel, so single-page app. Mostly write one 158 00:06:51,759 --> 00:06:54,930 language. It's backbone JavaScript, et cetera. But it is 159 00:06:54,930 --> 00:06:57,190 not Rails. So I think it takes, it still 160 00:06:57,190 --> 00:06:59,440 took me awhile, even with this render thing, to 161 00:06:59,440 --> 00:07:01,759 like, create an app that was good. And Rails 162 00:07:01,759 --> 00:07:03,490 is just much easier to create like, the vanilla 163 00:07:03,490 --> 00:07:06,410 example apps using, like, scaffolding or even not using 164 00:07:06,410 --> 00:07:08,860 scaffolding. It's just way faster for development. So I 165 00:07:08,860 --> 00:07:10,389 still think this is bad even though it's the 166 00:07:10,389 --> 00:07:12,699 closest thing to the Holy Grail today. 167 00:07:12,699 --> 00:07:16,370 But, my point is that Rails, I'm, I'm worried, 168 00:07:16,370 --> 00:07:17,780 because I think Rails is kind of getting left 169 00:07:17,780 --> 00:07:19,419 in the dust in this respect. Like, it's kind 170 00:07:19,419 --> 00:07:21,840 of, there's not really like an established solution for 171 00:07:21,840 --> 00:07:25,860 building like a thick client good experience Rails app. 172 00:07:25,860 --> 00:07:29,039 And so now I'm gonna show you some sort 173 00:07:29,039 --> 00:07:32,100 of solutions that get part way there. So let's 174 00:07:32,100 --> 00:07:33,430 look at those. 175 00:07:33,430 --> 00:07:35,560 So one option, and, you know, this is kind 176 00:07:35,560 --> 00:07:36,860 of a joke but it's a serious thing that 177 00:07:36,860 --> 00:07:39,520 people actually do, is creating one version of your 178 00:07:39,520 --> 00:07:42,009 app that lives on the client, and one version 179 00:07:42,009 --> 00:07:43,930 of your app that lives on the server. And 180 00:07:43,930 --> 00:07:45,759 so, you know, in this example you would write 181 00:07:45,759 --> 00:07:48,289 erb or HAML on the server, and then you 182 00:07:48,289 --> 00:07:50,330 would have an API that returns JSON from the 183 00:07:50,330 --> 00:07:52,509 server to the client, and then the client would 184 00:07:52,509 --> 00:07:54,360 figure out how to render new parts of the 185 00:07:54,360 --> 00:07:56,130 page that it wants to snap in using like 186 00:07:56,130 --> 00:07:59,740 some kind of frontend like handlebar or underscore.js templates. 187 00:07:59,740 --> 00:08:03,069 Right, so this seems kind of reasonable. But the 188 00:08:03,069 --> 00:08:05,720 problem is if you forget to update both templates 189 00:08:05,720 --> 00:08:07,410 at the same time, you're gonna end up with 190 00:08:07,410 --> 00:08:09,819 some inconsistency between the client and the server in 191 00:08:09,819 --> 00:08:12,020 terms of the logic. And this can be very, 192 00:08:12,020 --> 00:08:13,870 very dangerous. It can lead to some hard to 193 00:08:13,870 --> 00:08:16,620 suss out bugs and, you know, we all know 194 00:08:16,620 --> 00:08:19,389 DRY is a good thing to strive towards. 195 00:08:19,389 --> 00:08:21,250 So this doesn't stack up very well. It's not 196 00:08:21,250 --> 00:08:25,680 DRY. It's SEO-friendly. It's a thick client. You didn't 197 00:08:25,680 --> 00:08:27,280 write mostly one language, though. You had to write 198 00:08:27,280 --> 00:08:28,699 a bunch of stuff on the client and the 199 00:08:28,699 --> 00:08:31,150 server. And we only get a half point for 200 00:08:31,150 --> 00:08:32,469 Rails. So you've gotta spend a lot of time 201 00:08:32,469 --> 00:08:35,490 still on the frontend noodling around there. 202 00:08:35,490 --> 00:08:38,690 All right. So Turbolinks are something you also might 203 00:08:38,690 --> 00:08:39,948 have heard of. You might be thinking, well I 204 00:08:39,948 --> 00:08:41,299 can just do this with Turbolinks. This is like 205 00:08:41,299 --> 00:08:44,769 a one-liner, right? So Turbolinks, the way it works, 206 00:08:44,769 --> 00:08:46,879 is you write just one set of views, and 207 00:08:46,879 --> 00:08:49,269 then when the user clicks on a link, you 208 00:08:49,269 --> 00:08:50,749 can just pop in the whole new page but 209 00:08:50,749 --> 00:08:52,910 save the browser instance. So you save on this 210 00:08:52,910 --> 00:08:57,029 overhead of, like, parsing and compiling CSS and interpreting 211 00:08:57,029 --> 00:08:59,829 JavaScript and, you know, running all this stuff. It, 212 00:08:59,829 --> 00:09:01,360 it's actually kind of expensive to spin up a 213 00:09:01,360 --> 00:09:04,199 browser instance for the client. So you, you eliminate 214 00:09:04,199 --> 00:09:07,309 all that overhead and your client is extremely simple. 215 00:09:07,309 --> 00:09:10,499 You basically have to write no JavaScript. 216 00:09:10,499 --> 00:09:13,899 So the problem is that Turbolinks kind of ends 217 00:09:13,899 --> 00:09:15,509 there. There's nowhere else to go. If you want 218 00:09:15,509 --> 00:09:17,069 to snap in, like, just a new part of 219 00:09:17,069 --> 00:09:19,220 the page, you've gotta write some kind of custom 220 00:09:19,220 --> 00:09:21,749 controller action that just returns that part of the 221 00:09:21,749 --> 00:09:24,139 page and then you've gotta use like some jQuery 222 00:09:24,139 --> 00:09:26,100 soup type thing to like snap that in and 223 00:09:26,100 --> 00:09:28,839 then you're relying upon your, your page structure. So 224 00:09:28,839 --> 00:09:33,059 that is not a great solution. 225 00:09:33,059 --> 00:09:34,579 But this works pretty well if you're trying to 226 00:09:34,579 --> 00:09:38,029 do, depending on what you're trying to do. So, 227 00:09:38,029 --> 00:09:41,800 you know, this is DRY. It is SEO-friendly. It's 228 00:09:41,800 --> 00:09:44,019 not really like a proper thick client, though. It's 229 00:09:44,019 --> 00:09:46,089 kind of like a fake thick client. Feels almost 230 00:09:46,089 --> 00:09:48,489 like a thick client. Not quite there. Mostly write 231 00:09:48,489 --> 00:09:50,869 one language. We've got that covered. We've also got 232 00:09:50,869 --> 00:09:53,050 Rails covered. So this is kind of why Turbolinks 233 00:09:53,050 --> 00:09:55,339 is so popular I think. Because it basically does 234 00:09:55,339 --> 00:09:58,009 what you want without much hassle. 235 00:09:58,009 --> 00:10:01,629 So there's also this Ember/Angular/Backbone type movement now. You 236 00:10:01,629 --> 00:10:03,089 might have sort of seen, there are a bunch 237 00:10:03,089 --> 00:10:05,069 of talks about this. People allude to it all 238 00:10:05,069 --> 00:10:07,239 the time. This is sort of the new way, 239 00:10:07,239 --> 00:10:09,509 this is the new wave of building Rails apps. 240 00:10:09,509 --> 00:10:11,540 So you just have a JSON API in your 241 00:10:11,540 --> 00:10:15,139 server, that's it. Your entire app experience lives on 242 00:10:15,139 --> 00:10:17,279 the client, so it lives in JavaScript or CoffeeScript, 243 00:10:17,279 --> 00:10:20,149 what have you. And the initial page load, the 244 00:10:20,149 --> 00:10:22,879 first time your user visits the site, they download 245 00:10:22,879 --> 00:10:24,689 like this whole JS app thing, and then that 246 00:10:24,689 --> 00:10:26,179 sort of boots up and figures out how to 247 00:10:26,179 --> 00:10:27,239 like render the site. 248 00:10:27,239 --> 00:10:30,059 And so this might remind you of new Twitter. 249 00:10:30,059 --> 00:10:32,749 So Twitter in like, 2010 I think released this 250 00:10:32,749 --> 00:10:35,230 new experience where they were claiming this, exactly. They 251 00:10:35,230 --> 00:10:36,739 were saying this is going to be much better 252 00:10:36,739 --> 00:10:38,850 for our users because we can just sort of 253 00:10:38,850 --> 00:10:42,170 like snap in a new Tweet when you click. 254 00:10:42,170 --> 00:10:44,129 And they actually found that this was kind of 255 00:10:44,129 --> 00:10:46,129 costly. Like, sometimes it would take ten seconds to 256 00:10:46,129 --> 00:10:49,220 render a 140 character Tweet. Because you had to 257 00:10:49,220 --> 00:10:51,579 download like all these assets and then like that 258 00:10:51,579 --> 00:10:53,149 would sort of like boot up, spin up and 259 00:10:53,149 --> 00:10:55,529 build the page. This isn't like an actually good 260 00:10:55,529 --> 00:10:57,689 experience for users, at least the first time they 261 00:10:57,689 --> 00:10:59,829 visit the page. It's actually pretty bad. 262 00:10:59,829 --> 00:11:03,600 So it doesn't quite stack up great here. It 263 00:11:03,600 --> 00:11:07,459 is DRY. It is not SEO friendly, though. Now, 264 00:11:07,459 --> 00:11:09,809 there's some tricks to sort of, making it, sort 265 00:11:09,809 --> 00:11:11,549 of making it SEO friendly, but, you know, for 266 00:11:11,549 --> 00:11:13,239 the most part it's kind of hard to make 267 00:11:13,239 --> 00:11:15,519 it, you know, allow your app to like serve 268 00:11:15,519 --> 00:11:17,920 HTML to a crawler. Now if you're not building 269 00:11:17,920 --> 00:11:20,189 a content site, maybe it doesn't matter. But, you 270 00:11:20,189 --> 00:11:21,989 know, my claim is this is pretty important on 271 00:11:21,989 --> 00:11:25,559 most websites. It's a thick client. You don't get 272 00:11:25,559 --> 00:11:27,610 to write mostly one language. Half of it's JavaScript. 273 00:11:27,610 --> 00:11:30,819 So, again, half point for Rails. 274 00:11:30,819 --> 00:11:33,329 So the point that I am trying to make 275 00:11:33,329 --> 00:11:36,209 here is that each of these things makes like 276 00:11:36,209 --> 00:11:38,379 a key, key trade off that we can't live 277 00:11:38,379 --> 00:11:40,779 without. So what are we actually going to do 278 00:11:40,779 --> 00:11:42,069 about this? 279 00:11:42,069 --> 00:11:43,899 Well, now I'm gonna show you like a new 280 00:11:43,899 --> 00:11:46,189 solution that, you know, maybe it's good, maybe it's 281 00:11:46,189 --> 00:11:51,290 not. And actually, this starts with a, sort of 282 00:11:51,290 --> 00:11:53,489 like, admission. So I kind of lied to you 283 00:11:53,489 --> 00:11:56,410 before. I told you I built this app that 284 00:11:56,410 --> 00:11:58,619 I was showing you before using render which is 285 00:11:58,619 --> 00:12:00,589 this like, node.js thing. But the truth is, I 286 00:12:00,589 --> 00:12:02,649 don't even know JavaScript. I don't even know anything 287 00:12:02,649 --> 00:12:05,290 about node.js. Render. I just read about it, right. 288 00:12:05,290 --> 00:12:09,160 I actually built this app using this new sort 289 00:12:09,160 --> 00:12:12,799 of like technique slash library called Perspective. 290 00:12:12,799 --> 00:12:15,069 So again, here's the same app. And just to 291 00:12:15,069 --> 00:12:18,059 remind you, you can kind of click around here 292 00:12:18,059 --> 00:12:20,799 and, you know, things just sort of load. And 293 00:12:20,799 --> 00:12:22,540 this is a very simple example, but things are 294 00:12:22,540 --> 00:12:25,029 snapping in, you know, just the parts of the 295 00:12:25,029 --> 00:12:27,749 page that are changing. Need to get changed. And 296 00:12:27,749 --> 00:12:29,939 you can sort like edit and save stuff. And 297 00:12:29,939 --> 00:12:32,259 we're just sort of updating parts of the page 298 00:12:32,259 --> 00:12:34,009 that need to change. 299 00:12:34,009 --> 00:12:36,999 And so this is this perspectives thing, which I'm 300 00:12:36,999 --> 00:12:39,179 claiming is better, right. So let's see how it 301 00:12:39,179 --> 00:12:42,769 stacks up on the chart that I just made. 302 00:12:42,769 --> 00:12:46,949 It's DRY. It's SEO-friendly. It's a thick client. You 303 00:12:46,949 --> 00:12:48,230 write mostly one lang- I think you see where 304 00:12:48,230 --> 00:12:50,720 this is going. And it's Rails. So I checked 305 00:12:50,720 --> 00:12:52,529 all the boxes in my own talk. This is 306 00:12:52,529 --> 00:12:55,429 a key, key thing. You have to be able 307 00:12:55,429 --> 00:12:57,049 to do this if you're gonna speak at RailsConf. 308 00:12:57,049 --> 00:12:59,839 You gotta have a chart, checks all the boxes. 309 00:12:59,839 --> 00:13:01,819 This is good. 310 00:13:01,819 --> 00:13:05,619 So, you know, the key sort of thing here, 311 00:13:05,619 --> 00:13:08,819 the key part of Perspectives, is that we want 312 00:13:08,819 --> 00:13:11,949 to be able to share our templates between the 313 00:13:11,949 --> 00:13:13,920 client and the server. So like the server should 314 00:13:13,920 --> 00:13:16,119 be able to render full HTML. And the client 315 00:13:16,119 --> 00:13:17,660 should be able to like receive JSON and like 316 00:13:17,660 --> 00:13:18,999 render a template, right. This is sort of the 317 00:13:18,999 --> 00:13:21,100 appeal of something like render. 318 00:13:21,100 --> 00:13:28,100 So, here, you know, let's, let's say we thought, 319 00:13:28,499 --> 00:13:30,709 well maybe we can sort of share templates. Maybe 320 00:13:30,709 --> 00:13:32,899 we can share our existing erb templates. Those are 321 00:13:32,899 --> 00:13:35,009 pretty easy to write. So here's like a simple 322 00:13:35,009 --> 00:13:36,939 erb template, right. We're just generating like a link 323 00:13:36,939 --> 00:13:38,649 to a user. We're using the name as like 324 00:13:38,649 --> 00:13:41,869 the anchor text. We're using user_url helper from Rails 325 00:13:41,869 --> 00:13:43,790 to like generate a link to it. This is 326 00:13:43,790 --> 00:13:47,399 pretty simple. You might imagine that using something like 327 00:13:47,399 --> 00:13:50,669 Opal, which transforms Ruby in JavaScript, you could like 328 00:13:50,669 --> 00:13:53,389 pour it your whole server, kind of like, instance, 329 00:13:53,389 --> 00:13:56,809 including all these helpers link link_to and user_url, to 330 00:13:56,809 --> 00:13:58,910 JavaScript, and then you could just jump down your 331 00:13:58,910 --> 00:14:01,029 erb template and then that could get sort of 332 00:14:01,029 --> 00:14:02,579 rendered on the client. 333 00:14:02,579 --> 00:14:04,410 This might, you know, you might think that this 334 00:14:04,410 --> 00:14:06,959 works. But, actually, you can kind of do more 335 00:14:06,959 --> 00:14:09,309 stuff in erb than you might sort of be 336 00:14:09,309 --> 00:14:11,730 aware of from simple examples. Like, you can, here's 337 00:14:11,730 --> 00:14:13,720 an example, where I'm actually just running like a 338 00:14:13,720 --> 00:14:16,529 SQL query in an erb template. And this, I 339 00:14:16,529 --> 00:14:21,509 think, demonstrates like, the fundamental difference - yeah, boo! 340 00:14:21,509 --> 00:14:24,779 This, I think, demonstrates like a fundamental difference between, 341 00:14:24,779 --> 00:14:27,549 you know, the client and the server, is that, 342 00:14:27,549 --> 00:14:30,419 they're kind of in different environments. Like, the server 343 00:14:30,419 --> 00:14:33,149 has access to resources that the client, not only 344 00:14:33,149 --> 00:14:35,329 doesn't have access to but shouldn't have access to. 345 00:14:35,329 --> 00:14:37,609 The client should not ever be able to like 346 00:14:37,609 --> 00:14:39,609 hook up to the database and ask some questions. 347 00:14:39,609 --> 00:14:42,179 Right, so. And the client is the same. Like, 348 00:14:42,179 --> 00:14:44,339 the client knows stuff about the user's browser. Like, 349 00:14:44,339 --> 00:14:46,660 they can inspect local storage and all this stuff. 350 00:14:46,660 --> 00:14:49,739 Like, they're fundamentally different environments. And so I don't 351 00:14:49,739 --> 00:14:52,279 think that any of the existing templates out there 352 00:14:52,279 --> 00:14:54,629 really get you this sort of shared environment for 353 00:14:54,629 --> 00:14:55,850 free. 354 00:14:55,850 --> 00:14:59,850 So, the way, you know, so the way to 355 00:14:59,850 --> 00:15:02,879 get to a shared template between a client and 356 00:15:02,879 --> 00:15:05,459 a server is to find the lowest common denominator. 357 00:15:05,459 --> 00:15:08,259 So, like, if you've taken, you know, calculus at 358 00:15:08,259 --> 00:15:10,209 the graduate level, you might have heard of the 359 00:15:10,209 --> 00:15:13,639 lowest common denominator. It's the way that you are 360 00:15:13,639 --> 00:15:16,329 able to like, if you're trying to add fractions, 361 00:15:16,329 --> 00:15:18,669 you can like, multiply the denominator- 362 00:15:18,669 --> 00:15:20,850 The point is, it allows you to like find 363 00:15:20,850 --> 00:15:24,519 some common ground between, you know, the client and 364 00:15:24,519 --> 00:15:28,160 the server, right. So we need lowest common denominator. 365 00:15:28,160 --> 00:15:30,389 Which is the dumbest possible template. So we need 366 00:15:30,389 --> 00:15:32,939 something that's really dumb, that has, that basically can't 367 00:15:32,939 --> 00:15:36,239 do anything. And so what is that? Well, that's 368 00:15:36,239 --> 00:15:39,399 mustache. Mustache are the dumbest templates out there. Don't 369 00:15:39,399 --> 00:15:40,669 tell them I said that. They're probably in the 370 00:15:40,669 --> 00:15:43,399 other room or something. But they're, they're pretty dumb. 371 00:15:43,399 --> 00:15:46,979 You know, you might have heard mustache templates referred 372 00:15:46,979 --> 00:15:49,919 to as being logic-less. I actually think logic-less is 373 00:15:49,919 --> 00:15:51,669 kind of like a bad way of describing it. 374 00:15:51,669 --> 00:15:53,919 Because when I hear logic-less, I'm kind of thinking, 375 00:15:53,919 --> 00:15:55,899 like, OK, I can't write like an if statement. 376 00:15:55,899 --> 00:15:58,850 There's probably no like for loop situation. Like, what 377 00:15:58,850 --> 00:15:59,859 else can't I do? Well I probably can't do 378 00:15:59,859 --> 00:16:02,329 like an if-else, like, you know, the reality is 379 00:16:02,329 --> 00:16:04,339 you can actually kind of do that stuff. It's 380 00:16:04,339 --> 00:16:06,199 called a different thing. So I don't like using 381 00:16:06,199 --> 00:16:07,509 the word logic-less. 382 00:16:07,509 --> 00:16:09,609 It's more like you can't run arbitrary code. It's 383 00:16:09,609 --> 00:16:13,069 more like no code, code-less or something. So you 384 00:16:13,069 --> 00:16:15,040 can't run arbitrary code. This is the sort of 385 00:16:15,040 --> 00:16:18,049 take away from mustache, right. And so, you know, 386 00:16:18,049 --> 00:16:20,199 this is kind of cool because, because you can't 387 00:16:20,199 --> 00:16:23,529 run arbitrary code, we can write mustache template renders 388 00:16:23,529 --> 00:16:26,350 in all these different languages. So you can easily 389 00:16:26,350 --> 00:16:29,829 render mustache templates in Ruby or JavaScript. If you 390 00:16:29,829 --> 00:16:31,489 want to use one of these other languages, these 391 00:16:31,489 --> 00:16:33,329 are terrible, but I guess you could use like 392 00:16:33,329 --> 00:16:35,069 dot net or something if you wanted to render 393 00:16:35,069 --> 00:16:37,619 a mustache template in dot net. I don't know 394 00:16:37,619 --> 00:16:38,619 what you're doing but you might be able to 395 00:16:38,619 --> 00:16:40,009 do that. 396 00:16:40,009 --> 00:16:42,489 So, to show you like how to create a 397 00:16:42,489 --> 00:16:43,839 mustache template, I want to look at like a 398 00:16:43,839 --> 00:16:46,869 specific example. So here's, like, the RailsGenius app, and, 399 00:16:46,869 --> 00:16:49,369 you know, in the left, lower left-hand corner here 400 00:16:49,369 --> 00:16:52,160 there's like an annotation, right. So this is sort 401 00:16:52,160 --> 00:16:55,619 of annotating the line node.js. And if we sort 402 00:16:55,619 --> 00:16:57,449 of zoom in on this thing, we can see 403 00:16:57,449 --> 00:16:59,660 there are a few different components. 404 00:16:59,660 --> 00:17:02,549 There's the section of text that's annotated. So we'll 405 00:17:02,549 --> 00:17:04,549 call that the referent. This is like a fancy 406 00:17:04,549 --> 00:17:07,309 word for like reference or something. So we'll call 407 00:17:07,309 --> 00:17:09,660 that the referent. That's the line that I highlighted 408 00:17:09,660 --> 00:17:12,160 and explained. And then we'll call this the sort 409 00:17:12,160 --> 00:17:15,059 of body. And you'll notice the body can contain 410 00:17:15,059 --> 00:17:17,959 like arbitrary HTML. There's a link to node.js dot 411 00:17:17,959 --> 00:17:20,099 org. A link to Ruby on Rails, et cetera. 412 00:17:20,099 --> 00:17:22,490 I'm sort of adding, like, you know, I'm adding 413 00:17:22,490 --> 00:17:25,459 hyper media here because it's the web. 414 00:17:25,459 --> 00:17:26,829 And then there's this edit link, right. And so 415 00:17:26,829 --> 00:17:28,860 this edit link, you might imagine, should appear for 416 00:17:28,860 --> 00:17:31,880 some users and not others depending on, like, what 417 00:17:31,880 --> 00:17:34,559 your permissions are or what your sort of situation 418 00:17:34,559 --> 00:17:36,690 is. 419 00:17:36,690 --> 00:17:39,659 And so mustache, the, the template for this, the 420 00:17:39,659 --> 00:17:42,230 whole template, looks like this. So I'm gonna go 421 00:17:42,230 --> 00:17:44,070 into like the specifics of how I would actually, 422 00:17:44,070 --> 00:17:46,389 you know, what this is doing. But here's the 423 00:17:46,389 --> 00:17:48,950 template. And to render this, I just need this 424 00:17:48,950 --> 00:17:51,639 hash of JSON data. So I can render this 425 00:17:51,639 --> 00:17:53,759 anywhere as long as I have this hash. Key 426 00:17:53,759 --> 00:17:55,850 thing to remember. 427 00:17:55,850 --> 00:18:00,600 So, if I can't run code in mustache, like 428 00:18:00,600 --> 00:18:03,610 I can run code in erb, how do I 429 00:18:03,610 --> 00:18:06,039 actually like put data in the markup, which is 430 00:18:06,039 --> 00:18:09,009 like the whole point of templates, right? 431 00:18:09,009 --> 00:18:11,299 So you can use these tags. Right, so given 432 00:18:11,299 --> 00:18:14,840 this section of JSON, you have a referent mapping 433 00:18:14,840 --> 00:18:18,139 to node dot js, right. We can render that 434 00:18:18,139 --> 00:18:21,029 data into this template with a, you know, inside 435 00:18:21,029 --> 00:18:23,130 of a block quote, by using this double curly 436 00:18:23,130 --> 00:18:26,230 brace thing. This just says, like, basically, gsub, or 437 00:18:26,230 --> 00:18:29,269 actually not gsub, sub this referant into, inside this 438 00:18:29,269 --> 00:18:30,710 block quote. Pretty simple. 439 00:18:30,710 --> 00:18:32,269 So this is just gonna print like block quote 440 00:18:32,269 --> 00:18:37,220 node.js, you know. That should hopefully be fairly self-evident. 441 00:18:37,220 --> 00:18:39,409 So if you want to sort of do something 442 00:18:39,409 --> 00:18:41,850 where you're printing raw HTML, the double brace will 443 00:18:41,850 --> 00:18:44,279 actually escape it. So that's most the time what 444 00:18:44,279 --> 00:18:46,389 you want. But in this case we're actually like, 445 00:18:46,389 --> 00:18:49,610 you know, we want hyper media in that annotation. 446 00:18:49,610 --> 00:18:51,830 So this, you know, actually has an href. An 447 00:18:51,830 --> 00:18:52,690 a tag, rather. 448 00:18:52,690 --> 00:18:55,440 So we're gonna use the triple brace, which is 449 00:18:55,440 --> 00:18:57,470 another type of tag that says print this HTML 450 00:18:57,470 --> 00:19:00,149 raw. So this will actually print out, like, you 451 00:19:00,149 --> 00:19:02,779 know, real anchor tag. Which is, in this case, 452 00:19:02,779 --> 00:19:05,559 what we want. So here is the sort of 453 00:19:05,559 --> 00:19:07,600 meat of mustache. This is probably the trickiest part 454 00:19:07,600 --> 00:19:10,399 of mustache. There's another type of tag which is 455 00:19:10,399 --> 00:19:13,990 this sort of double brace hash block, right. 456 00:19:13,990 --> 00:19:16,960 So here is the block that I'm talking about. 457 00:19:16,960 --> 00:19:18,330 So you can see this double brace, and then 458 00:19:18,330 --> 00:19:20,820 there's hash edit. This hash is kind of where 459 00:19:20,820 --> 00:19:23,080 the logic by another name comes into play in 460 00:19:23,080 --> 00:19:25,610 mustache. So this is going to, if edit is 461 00:19:25,610 --> 00:19:27,880 like, a boolean type thing, it's going to run, 462 00:19:27,880 --> 00:19:30,370 or, or go into the block. If edit is 463 00:19:30,370 --> 00:19:33,639 true, if edit is like a list of something, 464 00:19:33,639 --> 00:19:35,340 it basically is your for loop is the way 465 00:19:35,340 --> 00:19:36,610 to think about it. 466 00:19:36,610 --> 00:19:37,960 There's one more thing that is like if edit 467 00:19:37,960 --> 00:19:40,190 is like a hash, it kind of just will 468 00:19:40,190 --> 00:19:44,409 run the intersection if the hash is there. Otherwise 469 00:19:44,409 --> 00:19:46,570 it won't. So in this case, we're just saying, 470 00:19:46,570 --> 00:19:48,220 you know, we should show the edit link. That's 471 00:19:48,220 --> 00:19:50,259 what edit true means. This is our logic by 472 00:19:50,259 --> 00:19:54,110 another name. And then we're actually, you know, grabbing 473 00:19:54,110 --> 00:19:57,340 the edit href from the JSON hash as well. 474 00:19:57,340 --> 00:19:59,009 And so this will result in just putting the, 475 00:19:59,009 --> 00:20:00,139 printing the edit link. 476 00:20:00,139 --> 00:20:03,090 Now if edit were false, it wouldn't print that. 477 00:20:03,090 --> 00:20:04,830 And so you might be asking, like, well what 478 00:20:04,830 --> 00:20:06,330 if I wanted to do something else. Like I'm 479 00:20:06,330 --> 00:20:09,860 used to writing these if-else statements. So mustache also 480 00:20:09,860 --> 00:20:12,970 has this other sort of tag, which is a 481 00:20:12,970 --> 00:20:16,750 carrot. SO there's like double, double squiggly, double curly 482 00:20:16,750 --> 00:20:19,440 brace, carot edit, which just means sort of go 483 00:20:19,440 --> 00:20:22,519 into this block if edit is unset or false. 484 00:20:22,519 --> 00:20:25,019 So this is the kind of last tag. So 485 00:20:25,019 --> 00:20:27,070 in this case, if edit were false, we would 486 00:20:27,070 --> 00:20:29,970 just print can't edit. So this is mustache. That's 487 00:20:29,970 --> 00:20:32,070 basically all you can do. 488 00:20:32,070 --> 00:20:34,779 So how does this actually help us? Well, I 489 00:20:34,779 --> 00:20:36,720 don't know if you guys remember, but at the 490 00:20:36,720 --> 00:20:40,230 beginning of this mustache section, I showed you this 491 00:20:40,230 --> 00:20:42,519 template and I said all you need to render 492 00:20:42,519 --> 00:20:44,980 this template is this hash. And I also told 493 00:20:44,980 --> 00:20:47,090 you that there's a Ruby library for this and 494 00:20:47,090 --> 00:20:48,779 a JavaScript library for this. 495 00:20:48,779 --> 00:20:49,710 So I think you might see where this is 496 00:20:49,710 --> 00:20:51,850 going. If we have some way of generating like 497 00:20:51,850 --> 00:20:54,549 a hash, anywhere, then we can render it, we 498 00:20:54,549 --> 00:20:57,070 can ship the template and the hash to any 499 00:20:57,070 --> 00:21:00,110 environment and like render it there. 500 00:21:00,110 --> 00:21:01,409 That's the point I'm trying to make. So how 501 00:21:01,409 --> 00:21:03,809 do we actually generate this hash? That's the sort 502 00:21:03,809 --> 00:21:05,639 of tricky part. Well I'm gonna do some handwaving 503 00:21:05,639 --> 00:21:08,080 here and say, well, this, Perspective's library might help 504 00:21:08,080 --> 00:21:10,289 us a little bit. 505 00:21:10,289 --> 00:21:12,809 So you know here's a traditional Rails view. This 506 00:21:12,809 --> 00:21:15,789 is like an erb template, right. And so what 507 00:21:15,789 --> 00:21:17,940 I'm saying is that if we split this into 508 00:21:17,940 --> 00:21:21,610 a template, which is mustache, and a perspective, which 509 00:21:21,610 --> 00:21:25,009 is something, it's a new type of object, then 510 00:21:25,009 --> 00:21:27,299 we can just have this data transport thing, which 511 00:21:27,299 --> 00:21:29,220 is just the hash, which is generated by the 512 00:21:29,220 --> 00:21:32,490 perspective. And then we can render the template anywhere. 513 00:21:32,490 --> 00:21:33,750 So this is how we render on the client 514 00:21:33,750 --> 00:21:35,610 or the server. 515 00:21:35,610 --> 00:21:37,750 So what is this perspective thing look like? Well, 516 00:21:37,750 --> 00:21:40,289 as you might imagine, it's a bunch of stuff 517 00:21:40,289 --> 00:21:44,370 that specifies what is in the hash. So, here's 518 00:21:44,370 --> 00:21:46,539 the whole perspective. I'm gonna dive into different parts 519 00:21:46,539 --> 00:21:48,580 of it. But you can see it's just basically 520 00:21:48,580 --> 00:21:50,710 a Ruby object with like some macros thrown in. 521 00:21:50,710 --> 00:21:52,470 That's, that's sort of the goal of the library. 522 00:21:52,470 --> 00:21:55,509 It should just be a Ruby object. Plain Ruby 523 00:21:55,509 --> 00:21:56,529 object. 524 00:21:56,529 --> 00:21:59,840 So you can specify inputs, which you specify with 525 00:21:59,840 --> 00:22:02,779 params. So you can say param annotation, this perspective 526 00:22:02,779 --> 00:22:07,870 expects an annotation as input. You can specify outputs. 527 00:22:07,870 --> 00:22:12,330 This perspective outputs reference, which is the annotation's referent 528 00:22:12,330 --> 00:22:16,279 property. It also specifies body as a key. And 529 00:22:16,279 --> 00:22:18,509 that's the annotation's body as HTML. So this is 530 00:22:18,509 --> 00:22:20,029 gonna be raw HTML. 531 00:22:20,029 --> 00:22:24,039 And so properties our output. And so these are 532 00:22:24,039 --> 00:22:26,799 actually just keys in this hash. So we can 533 00:22:26,799 --> 00:22:30,929 just turn this perspective object into a JSON object 534 00:22:30,929 --> 00:22:32,960 and then that can be rendered anywhere. So now 535 00:22:32,960 --> 00:22:35,690 that we know what this perspective object is, it 536 00:22:35,690 --> 00:22:37,940 should be pretty self-explanatory how we get from the 537 00:22:37,940 --> 00:22:40,529 right over to the left and render this template. 538 00:22:40,529 --> 00:22:42,590 Now you might be thinking, isn't this just like 539 00:22:42,590 --> 00:22:45,649 a fancy version of like helpers or something? Like, 540 00:22:45,649 --> 00:22:48,750 helpers with like a namespace? And it's actually different 541 00:22:48,750 --> 00:22:52,139 because, you know, helpers are sort of operating at, 542 00:22:52,139 --> 00:22:54,129 they seem like they kind of live in their 543 00:22:54,129 --> 00:22:57,379 own separate object, like annotations' helper or something. But 544 00:22:57,379 --> 00:22:59,909 actually they're in a global namespace which can be 545 00:22:59,909 --> 00:23:02,029 called from any template at any time. And so 546 00:23:02,029 --> 00:23:04,159 they can kind of like override each other. 547 00:23:04,159 --> 00:23:06,809 They also are direct function indication. So this is 548 00:23:06,809 --> 00:23:09,100 just data. This hash in the middle is just 549 00:23:09,100 --> 00:23:12,070 data. SO like if you reference a property twice, 550 00:23:12,070 --> 00:23:14,240 you're always gonna get the same value, unlike a 551 00:23:14,240 --> 00:23:16,590 helper, which could theoretically return different things if you 552 00:23:16,590 --> 00:23:18,620 call it different times. SO it's kind of like 553 00:23:18,620 --> 00:23:22,460 a safer thing for us as developers. 554 00:23:22,460 --> 00:23:25,429 And so to build like an app with this, 555 00:23:25,429 --> 00:23:27,649 you can imagine the initial request that the client 556 00:23:27,649 --> 00:23:30,879 makes will receive HTML so the, the server will 557 00:23:30,879 --> 00:23:33,669 say, OK let me take this perspective thing, turn 558 00:23:33,669 --> 00:23:35,919 it into JSON, render in mustache template and then 559 00:23:35,919 --> 00:23:37,870 send that back to the user. And, in the 560 00:23:37,870 --> 00:23:39,659 case of like new Twitter, the user would just 561 00:23:39,659 --> 00:23:42,179 see the 140 character Tweet rendered. And in the 562 00:23:42,179 --> 00:23:45,240 case of like a web-crawler for a search engine, 563 00:23:45,240 --> 00:23:46,509 it would see like the full HTML that it 564 00:23:46,509 --> 00:23:47,799 can then index. 565 00:23:47,799 --> 00:23:50,019 And then subsequent requests, just like we would do 566 00:23:50,019 --> 00:23:52,330 with like Ember or Backbone or whatever, we just 567 00:23:52,330 --> 00:23:54,570 request JSON from the server and then we render 568 00:23:54,570 --> 00:23:58,519 the part of the page that needs to change. 569 00:23:58,519 --> 00:24:02,080 So, you the know, the key thing here I 570 00:24:02,080 --> 00:24:05,659 think is that HTML is unstructured data. And so 571 00:24:05,659 --> 00:24:08,049 a lot of like sort of Rails patterns will 572 00:24:08,049 --> 00:24:10,620 tell you just return like the snippet of HTML 573 00:24:10,620 --> 00:24:12,889 from the server that you need and then snap 574 00:24:12,889 --> 00:24:15,809 that in somewhere. And the eventually leads to like 575 00:24:15,809 --> 00:24:20,090 soupy code and coupling to like classes on HTML 576 00:24:20,090 --> 00:24:21,929 elements, which leads to a lot of like weirdo 577 00:24:21,929 --> 00:24:24,049 bugs that are hard to track down. 578 00:24:24,049 --> 00:24:26,830 JSON, on the other hand, is structured data. It's 579 00:24:26,830 --> 00:24:29,279 a lot easier to deal with this, so, you 580 00:24:29,279 --> 00:24:31,350 can either render it or you could do something, 581 00:24:31,350 --> 00:24:33,809 you know, on the client that's a little fancier. 582 00:24:33,809 --> 00:24:35,360 If you want to do, update different parts of 583 00:24:35,360 --> 00:24:37,649 the page, whatever. The point is that it's structured 584 00:24:37,649 --> 00:24:39,470 and it's easy to deal with. And if you're 585 00:24:39,470 --> 00:24:43,120 building out like a thick client, you want to 586 00:24:43,120 --> 00:24:47,769 couple your client experience to structured data, not unstructured 587 00:24:47,769 --> 00:24:48,659 data. 588 00:24:48,659 --> 00:24:51,779 All right, so I'm gonna do the quick getting 589 00:24:51,779 --> 00:24:53,299 started. You know this is, this is sort of 590 00:24:53,299 --> 00:24:54,830 about this library, but I don't want it to 591 00:24:54,830 --> 00:24:56,490 be all about this library. So, you know, it's 592 00:24:56,490 --> 00:24:58,809 just a gem. You can just generate the install 593 00:24:58,809 --> 00:25:01,929 for it. That'll like make your app perspectivified. You 594 00:25:01,929 --> 00:25:05,220 can scaffold stuff. You know, you break your erb 595 00:25:05,220 --> 00:25:10,309 templates into mustache templates and a perspective. And you 596 00:25:10,309 --> 00:25:13,259 just add this one line to your controller, so 597 00:25:13,259 --> 00:25:15,029 this just uses a responder to figure out if 598 00:25:15,029 --> 00:25:18,120 the client wants HTML or wants JSON, and turns 599 00:25:18,120 --> 00:25:19,840 the perspective into whatever you want to. In this 600 00:25:19,840 --> 00:25:22,710 case, it's just, you know, find this annotation by 601 00:25:22,710 --> 00:25:26,090 ID. Use this little macro to create your perspective 602 00:25:26,090 --> 00:25:27,769 and pass it the data it needs, which in 603 00:25:27,769 --> 00:25:29,659 this case is like an annotation. And then we 604 00:25:29,659 --> 00:25:33,649 can render a JSON version or an HTML version. 605 00:25:33,649 --> 00:25:37,710 So what else does this buy us? So clearly 606 00:25:37,710 --> 00:25:39,639 this rendering on the client and server thing is 607 00:25:39,639 --> 00:25:43,320 pretty good. But actually, I didn't like set out, 608 00:25:43,320 --> 00:25:45,120 when I was thinking about this, to like build 609 00:25:45,120 --> 00:25:47,399 some sort of like new thick client like framework 610 00:25:47,399 --> 00:25:49,600 thing that competes with Ember. That wasn't my goal 611 00:25:49,600 --> 00:25:52,879 and I'm still not sure that's my goal. The 612 00:25:52,879 --> 00:25:54,509 benefits I'm about to tell you about were actually 613 00:25:54,509 --> 00:25:57,139 like the initial inspiration for like wanting to build 614 00:25:57,139 --> 00:25:58,139 this library. 615 00:25:58,139 --> 00:26:02,909 So, number one is separation of concerns. So, I 616 00:26:02,909 --> 00:26:06,860 really hate seeing erb templates like this. Here's like 617 00:26:06,860 --> 00:26:08,649 an erb version of the template I just showed 618 00:26:08,649 --> 00:26:10,679 you. So instead of having like a nice edit 619 00:26:10,679 --> 00:26:14,200 property, there's often like some logic in here, if 620 00:26:14,200 --> 00:26:17,389 you look at the bottom there, that's checking, like, 621 00:26:17,389 --> 00:26:18,970 whether or not to show the edit link. And 622 00:26:18,970 --> 00:26:20,730 this is kind of ugly. It's kind of ugly 623 00:26:20,730 --> 00:26:23,240 no matter where it lives. But it's especially ugly 624 00:26:23,240 --> 00:26:24,519 if it lives in a template. 625 00:26:24,519 --> 00:26:26,059 And it is so easy to do this with 626 00:26:26,059 --> 00:26:29,120 erb, cause, you know, erb literally just means embedded 627 00:26:29,120 --> 00:26:31,509 Ruby. So you can just write anything. Like I, 628 00:26:31,509 --> 00:26:33,610 like I've seen saying. SO like here we're saying, 629 00:26:33,610 --> 00:26:36,509 the person can edit the annotation if they created 630 00:26:36,509 --> 00:26:39,379 or they're like a super admin type, type, type 631 00:26:39,379 --> 00:26:41,929 user. 632 00:26:41,929 --> 00:26:47,419 So, mustache and perspectives force you into this separation 633 00:26:47,419 --> 00:26:49,850 of concerns, where you literally can't write any code 634 00:26:49,850 --> 00:26:51,789 in your template. So you have to put it 635 00:26:51,789 --> 00:26:54,110 in the perspective, which is just a Ruby object, 636 00:26:54,110 --> 00:26:56,090 which is where it kind of belongs. And there's 637 00:26:56,090 --> 00:26:59,600 no, there's no love for this in erb land 638 00:26:59,600 --> 00:27:01,490 in Rails. You're kind of, you're kind of off 639 00:27:01,490 --> 00:27:03,370 in this waste land of like, I guess I'll 640 00:27:03,370 --> 00:27:05,360 throw some view logic in here. I don't really 641 00:27:05,360 --> 00:27:07,580 know where it's supposed to go. 642 00:27:07,580 --> 00:27:08,970 And so this, this leads me to like, so 643 00:27:08,970 --> 00:27:11,440 here's the, sorry, here's the perspective version of it, 644 00:27:11,440 --> 00:27:14,029 where actually just generate this edit property and say 645 00:27:14,029 --> 00:27:15,889 whether or not we want to display the link, 646 00:27:15,889 --> 00:27:19,460 based on that logic I showed you before. 647 00:27:19,460 --> 00:27:20,799 So this also gives you like, testing. So I 648 00:27:20,799 --> 00:27:22,830 now DHH was like, you know, shitting on this 649 00:27:22,830 --> 00:27:26,230 in his talk. I still think testing is important. 650 00:27:26,230 --> 00:27:28,179 Maybe not TDD. But like the point is, if 651 00:27:28,179 --> 00:27:30,720 you wanted to test like an erb template and 652 00:27:30,720 --> 00:27:33,200 had some logic in this, in it, you would 653 00:27:33,200 --> 00:27:34,820 have to like, render, the only thing you can 654 00:27:34,820 --> 00:27:36,730 do is render the template. You can't talk to 655 00:27:36,730 --> 00:27:38,200 it. It's not an object. You can't ask it 656 00:27:38,200 --> 00:27:40,320 questions. All you can do is render it and 657 00:27:40,320 --> 00:27:41,990 then do like a string-match on it. 658 00:27:41,990 --> 00:27:43,169 And in fact, I've seen a ton of tests 659 00:27:43,169 --> 00:27:45,929 like this. Web driver tests are basically just doing 660 00:27:45,929 --> 00:27:48,320 like, advanced regexes to like figure out if the 661 00:27:48,320 --> 00:27:51,490 logic is right. And this is really bad. A 662 00:27:51,490 --> 00:27:53,869 perspective is just a freakin' object. Like you just 663 00:27:53,869 --> 00:27:55,690 new it up and pass it the data it 664 00:27:55,690 --> 00:27:57,779 needs and then you can test your logic. SO 665 00:27:57,779 --> 00:28:00,009 here I'm just creating a test double. You know, 666 00:28:00,009 --> 00:28:02,450 test doubles are important in testing. Test double for 667 00:28:02,450 --> 00:28:04,950 a user, test double for an annotation. I'm creating 668 00:28:04,950 --> 00:28:07,899 this new perspective and then I'm asking it if 669 00:28:07,899 --> 00:28:10,399 the edit link is true and verifying that it 670 00:28:10,399 --> 00:28:13,659 should be showing that. 671 00:28:13,659 --> 00:28:16,659 So another thing is caching. So this is like 672 00:28:16,659 --> 00:28:19,399 maybe a little bit difficult to motivate, but like, 673 00:28:19,399 --> 00:28:22,399 this sort of like cache digest thing, Russian doll 674 00:28:22,399 --> 00:28:23,789 caching thing is kind of hard for me to 675 00:28:23,789 --> 00:28:25,950 like wrap my brain around, right. Like, you have 676 00:28:25,950 --> 00:28:27,850 to, you have to write, sometimes, like a special 677 00:28:27,850 --> 00:28:30,429 comment to get the templates to know about each 678 00:28:30,429 --> 00:28:33,840 other. Not as good as just having objects that 679 00:28:33,840 --> 00:28:34,789 know about each other. 680 00:28:34,789 --> 00:28:38,220 So if you want to cache an annotation show 681 00:28:38,220 --> 00:28:40,450 perspective, you just use this cache macro and that 682 00:28:40,450 --> 00:28:44,429 says, use the annotation as the cache key, right. 683 00:28:44,429 --> 00:28:46,440 And so if you're familiar with, like, cache keys 684 00:28:46,440 --> 00:28:48,889 in Rails, if you're using generational caching, this will 685 00:28:48,889 --> 00:28:50,330 just say, the cache key - hopefully you can 686 00:28:50,330 --> 00:28:52,600 see this - is just the type of object, 687 00:28:52,600 --> 00:28:54,279 the id of the object, and when it was 688 00:28:54,279 --> 00:28:55,139 last updated. 689 00:28:55,139 --> 00:28:56,600 So this will like fall out of cache if 690 00:28:56,600 --> 00:28:58,999 anyone updates the annotation or if it's like a 691 00:28:58,999 --> 00:29:00,980 different annotation it'll have a different cache key. So 692 00:29:00,980 --> 00:29:05,100 this sort of, hopefully this is, is somewhat familiar. 693 00:29:05,100 --> 00:29:07,240 If you have another template that you're rendering, like 694 00:29:07,240 --> 00:29:11,409 here, this annotation show perspective, is rendering a nested 695 00:29:11,409 --> 00:29:13,690 user slash avatar perspective, so you can see that 696 00:29:13,690 --> 00:29:16,340 at the bottom. You might want to say, well, 697 00:29:16,340 --> 00:29:18,639 if the user updates their avatar, we also want 698 00:29:18,639 --> 00:29:19,700 this to fall out of cache. 699 00:29:19,700 --> 00:29:22,169 This is sort of the, the Russian doll caching 700 00:29:22,169 --> 00:29:24,629 of it all, right. So if the inside Russian 701 00:29:24,629 --> 00:29:26,960 doll is uncached then it should bust the outside 702 00:29:26,960 --> 00:29:30,179 Russian dolls cache key. So this thing, you can 703 00:29:30,179 --> 00:29:32,639 also assign a cache key to. You can say, 704 00:29:32,639 --> 00:29:34,379 cache based on the user. So if the user 705 00:29:34,379 --> 00:29:37,379 gets updated from the user's avatar perspective, we want 706 00:29:37,379 --> 00:29:39,960 this to fall out of cache. And so, like 707 00:29:39,960 --> 00:29:41,549 I said, we want the whole thing to fall 708 00:29:41,549 --> 00:29:43,659 out of cache if the user gets updated or 709 00:29:43,659 --> 00:29:45,679 the annotation gets updated. 710 00:29:45,679 --> 00:29:47,690 And so what perspective will do for you is 711 00:29:47,690 --> 00:29:50,119 say, OK, we know that there's a nested user's 712 00:29:50,119 --> 00:29:52,840 avatar perspective here, and so to generate the cache 713 00:29:52,840 --> 00:29:54,889 key for this whole thing, we're just going to 714 00:29:54,889 --> 00:29:57,929 concatenate the cache key from the annotation and the 715 00:29:57,929 --> 00:30:00,269 cache key from the user and produce this ugly, 716 00:30:00,269 --> 00:30:02,090 terrible, long cache key, which you don't have to 717 00:30:02,090 --> 00:30:04,639 worry about at any point as the writer of 718 00:30:04,639 --> 00:30:05,649 the code. 719 00:30:05,649 --> 00:30:07,759 So this is all sort of handled transparently for 720 00:30:07,759 --> 00:30:12,249 you. So are we ready to sail off, to 721 00:30:12,249 --> 00:30:14,980 drive off into the sunset in Rails land now 722 00:30:14,980 --> 00:30:18,879 with this new stuff? Well, not quite. The, the 723 00:30:18,879 --> 00:30:21,499 point I'm trying to make here is that, or 724 00:30:21,499 --> 00:30:22,529 one thing I want to get across here is 725 00:30:22,529 --> 00:30:24,249 that this is sort of a nascent library slash 726 00:30:24,249 --> 00:30:28,080 weekend project motivated by, you know, having, making it 727 00:30:28,080 --> 00:30:31,879 annoying to like, do caching, and it's hard to 728 00:30:31,879 --> 00:30:35,100 kind of separate your, your templates out, and also 729 00:30:35,100 --> 00:30:36,600 I'd like to be able to like render the 730 00:30:36,600 --> 00:30:39,659 same thing on the client and server. But there's 731 00:30:39,659 --> 00:30:41,100 still a bunch of stuff to be done, right. 732 00:30:41,100 --> 00:30:42,840 Like there's still some work to be done to 733 00:30:42,840 --> 00:30:45,590 like integrate this with existing like frontend frameworks if 734 00:30:45,590 --> 00:30:48,419 you want to add like a bunch more rich 735 00:30:48,419 --> 00:30:50,700 experiences on the client. 736 00:30:50,700 --> 00:30:53,600 And I want to get to the point, though, 737 00:30:53,600 --> 00:30:55,549 where we can have a good answer to these 738 00:30:55,549 --> 00:30:57,409 node.js libraries. Like this is a big motivation. Like 739 00:30:57,409 --> 00:31:00,110 I'm tired of node.js being, like, well let's just 740 00:31:00,110 --> 00:31:04,779 embrace JavaScript. Like, no let's not embrace JavaScript. Ruby. 741 00:31:04,779 --> 00:31:08,059 Ruby is better. So let's, let's get at them. 742 00:31:08,059 --> 00:31:10,009 But, the key take away is you shouldn't be 743 00:31:10,009 --> 00:31:12,499 sort of creating one version of your app that 744 00:31:12,499 --> 00:31:14,110 lives on the server and one that lives on 745 00:31:14,110 --> 00:31:17,299 the client. The ideal situation is move most of 746 00:31:17,299 --> 00:31:19,409 the stuff to the server but be able to 747 00:31:19,409 --> 00:31:23,110 like still create this thick client situation. 748 00:31:23,110 --> 00:31:25,440 So that's it. That's my talk. You can check 749 00:31:25,440 --> 00:31:28,970 out this library by going to RapGenius slash perspectives 750 00:31:28,970 --> 00:31:31,139 on GitHub, or if you're lazy, there's this bit.ly 751 00:31:31,139 --> 00:31:34,039 link. bit.ly slash RG perspectives. And also, as I 752 00:31:34,039 --> 00:31:36,659 said at the beginning of the talk, we are 753 00:31:36,659 --> 00:31:38,980 hiring. So if you're sort of interested in this 754 00:31:38,980 --> 00:31:41,809 kind of stuff or other stuff Rap Genius related, 755 00:31:41,809 --> 00:31:43,149 get at me. Hit me up on Twitter. Hit 756 00:31:43,149 --> 00:31:45,879 me up via email. Andy at RapGenius dot com. 757 00:31:45,879 --> 00:31:48,199 And I think we have time for some questions.