0:00:16.920,0:00:19.920 ANDREW WARNER: Welcome. I an Andrew Warner. 0:00:19.930,0:00:22.169 I am the director of engineering at 0:00:22.169,0:00:24.820 RapGenius dot com. You can follow me 0:00:24.820,0:00:28.089 on Twitter at wwarner. And you can also 0:00:28.089,0:00:30.710 follow RapGenius on Twitter at RapGenius. 0:00:30.710,0:00:32.598 So Tweet at me during the presentation, 0:00:32.598,0:00:34.690 after the presentation, tomorrow. 0:00:34.690,0:00:38.210 Whatever. I'm down. I will respond to your[br]stuff. 0:00:38.210,0:00:40.649 So, this is really exciting for me. This is 0:00:40.649,0:00:43.890 my first RailsConf speaking. And so, you know,[br]I'm 0:00:43.890,0:00:47.970 super excited to be here. Come on. Little[br]round 0:00:47.970,0:00:50.470 of applause. Yeah. Yeah. 0:00:50.470,0:00:53.420 This is very exciting for me, not just because 0:00:53.420,0:00:55.680 I'm speaking, but also because you all, you[br]know, 0:00:55.680,0:00:57.689 this is a pretty full room. You all chose 0:00:57.689,0:00:59.559 my talk over the other two talks! This is, 0:00:59.559,0:01:01.460 you know, it makes me feel good. It also 0:01:01.460,0:01:03.559 is crazy, because, how do you even know what 0:01:03.559,0:01:05.790 I'm gonna be talking about? I had some summary 0:01:05.790,0:01:07.540 that's kind of vague. Like, maybe I'm gonna[br]say 0:01:07.540,0:01:09.360 some stuff, but, you know, maybe I'm gonna[br]change 0:01:09.360,0:01:10.740 it a little bit. Now I've got this slide 0:01:10.740,0:01:12.500 on the screen that says Rails Holy Grail.[br]Who 0:01:12.500,0:01:14.890 knows what that even means? So, you know,[br]I'm 0:01:14.890,0:01:17.260 excited that you chose me even besides all[br]this 0:01:17.260,0:01:17.560 stuff. 0:01:17.560,0:01:20.890 So, you know, I'm gonna be talking today about 0:01:20.890,0:01:22.500 the Rails Holy Grail. I'm a little bit disappointed 0:01:22.500,0:01:24.940 that DHH kind of stole my thunder with his 0:01:24.940,0:01:27.409 Holy Grail slide. But, you know, I, I still, 0:01:27.409,0:01:29.470 I'm gonna use it. I couldn't find another[br]replacement 0:01:29.470,0:01:31.530 Holy Grail slide in the meantime. 0:01:31.530,0:01:33.890 So, I guess, what am I gonna be telling 0:01:33.890,0:01:36.530 you about? Well, first, I'm gonna be talking[br]to 0:01:36.530,0:01:38.500 you about what the Holy Grail is. So what 0:01:38.500,0:01:40.810 I mean when I say the Holy Grail. I'm 0:01:40.810,0:01:43.140 gonna be showing you some existing Rails solutions[br]that 0:01:43.140,0:01:45.920 kind of get us close to this. I'm going 0:01:45.920,0:01:47.810 to be offering up a new solution for your 0:01:47.810,0:01:51.760 consideration today. And I'm gonna show you[br]what else 0:01:51.760,0:01:54.760 this new solution gets us. 0:01:54.760,0:01:58.710 So, first off, what is the Holy Grail of 0:01:58.710,0:02:01.080 the web? This background is like the song[br]Holy 0:02:01.080,0:02:04.090 Grail by Jay-Z. I don't know. So, the Holy 0:02:04.090,0:02:06.010 Grail of the web, what I actually mean when 0:02:06.010,0:02:08.860 I say Holy Grail, is the best possible user 0:02:08.860,0:02:14.090 experience combined with the best possible[br]developer experience. So 0:02:14.090,0:02:15.840 it should be very easy for me to rapidly 0:02:15.840,0:02:19.319 develop an application, as a developer, that[br]is also 0:02:19.319,0:02:22.750 easy to use for a user. 0:02:22.750,0:02:25.440 And so what is the best possible user experience? 0:02:25.440,0:02:28.730 Well, I'm talking about sort of a, a single-page 0:02:28.730,0:02:31.230 app thick client feel. So you shouldn't have[br]to 0:02:31.230,0:02:34.790 reload the entire page every time you, every[br]time 0:02:34.790,0:02:37.280 the user actually clicks on a link. So in 0:02:37.280,0:02:39.330 2004, when Rails came out, it was really great 0:02:39.330,0:02:42.440 because it allowed you to create, very quickly,[br]websites 0:02:42.440,0:02:44.510 which were kind of a thin client, where every 0:02:44.510,0:02:46.349 single click reloaded the whole page. 0:02:46.349,0:02:48.459 And this was revolutionary. Before that, you[br]know, it 0:02:48.459,0:02:51.260 was really difficult to make a site rapidly.[br]And 0:02:51.260,0:02:54.190 around the same time, actually, Google released[br]this Gmail 0:02:54.190,0:02:55.560 thing. Kind of hard to see the screenshot,[br]but 0:02:55.560,0:02:58.630 I think you're all familiar with what Gmail[br]actually 0:02:58.630,0:03:01.959 is. Gmail was this single-page app where every[br]single 0:03:01.959,0:03:04.700 click actually loaded right on the same page[br]that 0:03:04.700,0:03:06.610 you were on whatever you content you wanted[br]to 0:03:06.610,0:03:08.000 see as the user. You didn't have to wait 0:03:08.000,0:03:10.650 for your whole browser to refresh. This is[br]pretty 0:03:10.650,0:03:13.090 good. So it's just no full page reloads at 0:03:13.090,0:03:15.069 all. This is the best experience for the user, 0:03:15.069,0:03:17.239 and it should sort of feel like a desktop 0:03:17.239,0:03:19.840 app or a mobile app in terms of the 0:03:19.840,0:03:21.450 native feel. 0:03:21.450,0:03:24.610 The best developer experience is a little[br]bit different. 0:03:24.610,0:03:26.879 So, you should be able to use a developer-friendly 0:03:26.879,0:03:28.650 framework. You should be able to rapidly develop[br]something. 0:03:28.650,0:03:31.860 You shouldn't have to reinvent the wheel.[br]Easy things 0:03:31.860,0:03:34.349 should be easy. So, Ruby on Rails is one 0:03:34.349,0:03:36.030 of these frameworks. You might have heard[br]of this. 0:03:36.030,0:03:39.120 Kind of why we're here today. So you should 0:03:39.120,0:03:41.250 be able to use a developer-friendly framework. 0:03:41.250,0:03:43.720 You should be DRY. You shouldn't have to repeat 0:03:43.720,0:03:46.680 yourself. D-R-Y. Don't Repeat Yourself. But[br]actually, what I 0:03:46.680,0:03:49.160 mean here is more like DRV. So what is 0:03:49.160,0:03:52.129 DRV? Well, I mean, you shouldn't have to repeat 0:03:52.129,0:03:53.690 views. You shouldn't have to write one set[br]of 0:03:53.690,0:03:56.209 views that lives on the client's browser and[br]one 0:03:56.209,0:03:58.810 set of the views that lives on your web 0:03:58.810,0:04:00.440 server. 0:04:00.440,0:04:02.540 You should be writing mostly one language.[br]At least, 0:04:02.540,0:04:04.230 in so far as views are concerned. So you 0:04:04.230,0:04:06.849 shouldn't have to context switch. Context[br]switching is very 0:04:06.849,0:04:09.550 expensive. Sort of switching from Ruby and[br]Rails to 0:04:09.550,0:04:13.069 JavaScript. This is difficult for us, as developers. 0:04:13.069,0:04:15.090 And your website should be SEO friendly. So[br]I 0:04:15.090,0:04:17.810 guess this part really applies to content[br]sites. So 0:04:17.810,0:04:21.459 I work at RapGenius dot com. Content and SEO 0:04:21.459,0:04:23.870 friendliness is extremely important for us.[br]We lost a 0:04:23.870,0:04:26.300 bunch of traffic when we actually got banned[br]from 0:04:26.300,0:04:28.750 Google for a little while. They showed us[br]exactly 0:04:28.750,0:04:31.720 how important SEO was. So your site should[br]be 0:04:31.720,0:04:35.280 able to show a crawler, a search engine crawler. 0:04:35.280,0:04:37.620 HTML that it can index and than make available 0:04:37.620,0:04:39.080 for users' searching. 0:04:39.080,0:04:42.090 So so what is the closest thing to this 0:04:42.090,0:04:44.560 Holy Grail today? 0:04:44.560,0:04:49.620 Well, it's kind of the node.js. There's a[br]node.js 0:04:49.620,0:04:50.960 solution that I think is the best thing. Come 0:04:50.960,0:04:54.930 on, boo node.js! Give me some boos. 0:04:54.930,0:04:57.400 So there's this Airbnb Rendr framework, right.[br]So this 0:04:57.400,0:05:00.490 says render your backbone JS apps on the client 0:05:00.490,0:05:03.380 and on the server using node.js. So this framework 0:05:03.380,0:05:05.880 is, you know, pretty easy to use. You write 0:05:05.880,0:05:09.530 your backbone JS client-side app and the client[br]can 0:05:09.530,0:05:11.380 sort of incrementally update the page and[br]this sort 0:05:11.380,0:05:14.680 of Gmail-like experience. And then the server[br]can also 0:05:14.680,0:05:18.970 render full HTML pages for arbitrarily deep[br]links. So 0:05:18.970,0:05:20.820 the user can still see a full HTML page 0:05:20.820,0:05:23.500 if they get deep-linked, and a web browser,[br]or 0:05:23.500,0:05:25.750 sorry, a web crawler for a search engine can 0:05:25.750,0:05:27.610 also see HTML. So this, I think, is the 0:05:27.610,0:05:29.940 best solution right there. Right, out there[br]today. 0:05:29.940,0:05:32.190 And here, I've actually built like a little[br]demo 0:05:32.190,0:05:33.750 app using render to show you how cool it 0:05:33.750,0:05:35.880 is. So this is a little bit washed out. 0:05:35.880,0:05:37.949 But, this is sort of a mini version of 0:05:37.949,0:05:41.270 our site RapGenius. It's, so RapGenius allows[br]you to 0:05:41.270,0:05:45.169 view documents and read documents and also[br]read inline 0:05:45.169,0:05:48.040 annotations on those documents. And the annotations[br]are meant 0:05:48.040,0:05:52.830 to provide context and also explanation, if[br]something's complicated, 0:05:52.830,0:05:54.370 and just add to the text. 0:05:54.370,0:05:56.970 So here I've built RailsGenius, which allows[br]you to 0:05:56.970,0:06:01.169 add context to, like, Rails talk abstracts.[br]So this 0:06:01.169,0:06:04.220 is my talk. And I've added some inline annotations 0:06:04.220,0:06:05.370 here, and the, the point I'm trying to make 0:06:05.370,0:06:06.970 is that we should be able to, when I 0:06:06.970,0:06:09.360 click this link, to add views, which is actually 0:06:09.360,0:06:11.780 an annotation, this shouldn't refresh the[br]whole page. It 0:06:11.780,0:06:13.530 should just load-in the part of the page that 0:06:13.530,0:06:15.759 changed. Which is a much better experience[br]for the 0:06:15.759,0:06:16.250 user. 0:06:16.250,0:06:17.810 So if I actually click on this, it just 0:06:17.810,0:06:19.650 loads that part of the page. You know, this 0:06:19.650,0:06:21.430 is something that, you know, might be familiar[br]to 0:06:21.430,0:06:23.539 you from using apps, but it's, it's kind of 0:06:23.539,0:06:25.090 hard to like do this out of the box 0:06:25.090,0:06:27.240 in Rails. And, you know, also you should be 0:06:27.240,0:06:29.289 able to like edit it right there and that 0:06:29.289,0:06:31.570 should just snap in the edit view, et cetera. 0:06:31.570,0:06:33.520 And this should not be too, too difficult[br]to 0:06:33.520,0:06:36.710 build. Looks like I lost my internet connection.[br]There 0:06:36.710,0:06:38.220 we go. 0:06:38.220,0:06:40.970 So this kind of stacks up pretty well. It's 0:06:40.970,0:06:44.300 DRY. We have one set of views. It's SEO-friendly. 0:06:44.300,0:06:48.280 You know, we can serve HTML the crawlers.[br]It's 0:06:48.280,0:06:51.759 a thick-client feel, so single-page app. Mostly[br]write one 0:06:51.759,0:06:54.930 language. It's backbone JavaScript, et cetera.[br]But it is 0:06:54.930,0:06:57.190 not Rails. So I think it takes, it still 0:06:57.190,0:06:59.440 took me awhile, even with this render thing,[br]to 0:06:59.440,0:07:01.759 like, create an app that was good. And Rails 0:07:01.759,0:07:03.490 is just much easier to create like, the vanilla 0:07:03.490,0:07:06.410 example apps using, like, scaffolding or even[br]not using 0:07:06.410,0:07:08.860 scaffolding. It's just way faster for development.[br]So I 0:07:08.860,0:07:10.389 still think this is bad even though it's the 0:07:10.389,0:07:12.699 closest thing to the Holy Grail today. 0:07:12.699,0:07:16.370 But, my point is that Rails, I'm, I'm worried, 0:07:16.370,0:07:17.780 because I think Rails is kind of getting left 0:07:17.780,0:07:19.419 in the dust in this respect. Like, it's kind 0:07:19.419,0:07:21.840 of, there's not really like an established[br]solution for 0:07:21.840,0:07:25.860 building like a thick client good experience[br]Rails app. 0:07:25.860,0:07:29.039 And so now I'm gonna show you some sort 0:07:29.039,0:07:32.100 of solutions that get part way there. So let's 0:07:32.100,0:07:33.430 look at those. 0:07:33.430,0:07:35.560 So one option, and, you know, this is kind 0:07:35.560,0:07:36.860 of a joke but it's a serious thing that 0:07:36.860,0:07:39.520 people actually do, is creating one version[br]of your 0:07:39.520,0:07:42.009 app that lives on the client, and one version 0:07:42.009,0:07:43.930 of your app that lives on the server. And 0:07:43.930,0:07:45.759 so, you know, in this example you would write 0:07:45.759,0:07:48.289 erb or HAML on the server, and then you 0:07:48.289,0:07:50.330 would have an API that returns JSON from the 0:07:50.330,0:07:52.509 server to the client, and then the client[br]would 0:07:52.509,0:07:54.360 figure out how to render new parts of the 0:07:54.360,0:07:56.130 page that it wants to snap in using like 0:07:56.130,0:07:59.740 some kind of frontend like handlebar or underscore.js[br]templates. 0:07:59.740,0:08:03.069 Right, so this seems kind of reasonable. But[br]the 0:08:03.069,0:08:05.720 problem is if you forget to update both templates 0:08:05.720,0:08:07.410 at the same time, you're gonna end up with 0:08:07.410,0:08:09.819 some inconsistency between the client and[br]the server in 0:08:09.819,0:08:12.020 terms of the logic. And this can be very, 0:08:12.020,0:08:13.870 very dangerous. It can lead to some hard to 0:08:13.870,0:08:16.620 suss out bugs and, you know, we all know 0:08:16.620,0:08:19.389 DRY is a good thing to strive towards. 0:08:19.389,0:08:21.250 So this doesn't stack up very well. It's not 0:08:21.250,0:08:25.680 DRY. It's SEO-friendly. It's a thick client.[br]You didn't 0:08:25.680,0:08:27.280 write mostly one language, though. You had[br]to write 0:08:27.280,0:08:28.699 a bunch of stuff on the client and the 0:08:28.699,0:08:31.150 server. And we only get a half point for 0:08:31.150,0:08:32.469 Rails. So you've gotta spend a lot of time 0:08:32.469,0:08:35.490 still on the frontend noodling around there. 0:08:35.490,0:08:38.690 All right. So Turbolinks are something you[br]also might 0:08:38.690,0:08:39.948 have heard of. You might be thinking, well[br]I 0:08:39.948,0:08:41.299 can just do this with Turbolinks. This is[br]like 0:08:41.299,0:08:44.769 a one-liner, right? So Turbolinks, the way[br]it works, 0:08:44.769,0:08:46.879 is you write just one set of views, and 0:08:46.879,0:08:49.269 then when the user clicks on a link, you 0:08:49.269,0:08:50.749 can just pop in the whole new page but 0:08:50.749,0:08:52.910 save the browser instance. So you save on[br]this 0:08:52.910,0:08:57.029 overhead of, like, parsing and compiling CSS[br]and interpreting 0:08:57.029,0:08:59.829 JavaScript and, you know, running all this[br]stuff. It, 0:08:59.829,0:09:01.360 it's actually kind of expensive to spin up[br]a 0:09:01.360,0:09:04.199 browser instance for the client. So you, you[br]eliminate 0:09:04.199,0:09:07.309 all that overhead and your client is extremely[br]simple. 0:09:07.309,0:09:10.499 You basically have to write no JavaScript. 0:09:10.499,0:09:13.899 So the problem is that Turbolinks kind of[br]ends 0:09:13.899,0:09:15.509 there. There's nowhere else to go. If you[br]want 0:09:15.509,0:09:17.069 to snap in, like, just a new part of 0:09:17.069,0:09:19.220 the page, you've gotta write some kind of[br]custom 0:09:19.220,0:09:21.749 controller action that just returns that part[br]of the 0:09:21.749,0:09:24.139 page and then you've gotta use like some jQuery 0:09:24.139,0:09:26.100 soup type thing to like snap that in and 0:09:26.100,0:09:28.839 then you're relying upon your, your page structure.[br]So 0:09:28.839,0:09:33.059 that is not a great solution. 0:09:33.059,0:09:34.579 But this works pretty well if you're trying[br]to 0:09:34.579,0:09:38.029 do, depending on what you're trying to do.[br]So, 0:09:38.029,0:09:41.800 you know, this is DRY. It is SEO-friendly.[br]It's 0:09:41.800,0:09:44.019 not really like a proper thick client, though.[br]It's 0:09:44.019,0:09:46.089 kind of like a fake thick client. Feels almost 0:09:46.089,0:09:48.489 like a thick client. Not quite there. Mostly[br]write 0:09:48.489,0:09:50.869 one language. We've got that covered. We've[br]also got 0:09:50.869,0:09:53.050 Rails covered. So this is kind of why Turbolinks 0:09:53.050,0:09:55.339 is so popular I think. Because it basically[br]does 0:09:55.339,0:09:58.009 what you want without much hassle. 0:09:58.009,0:10:01.629 So there's also this Ember/Angular/Backbone[br]type movement now. You 0:10:01.629,0:10:03.089 might have sort of seen, there are a bunch 0:10:03.089,0:10:05.069 of talks about this. People allude to it all 0:10:05.069,0:10:07.239 the time. This is sort of the new way, 0:10:07.239,0:10:09.509 this is the new wave of building Rails apps. 0:10:09.509,0:10:11.540 So you just have a JSON API in your 0:10:11.540,0:10:15.139 server, that's it. Your entire app experience[br]lives on 0:10:15.139,0:10:17.279 the client, so it lives in JavaScript or CoffeeScript, 0:10:17.279,0:10:20.149 what have you. And the initial page load,[br]the 0:10:20.149,0:10:22.879 first time your user visits the site, they[br]download 0:10:22.879,0:10:24.689 like this whole JS app thing, and then that 0:10:24.689,0:10:26.179 sort of boots up and figures out how to 0:10:26.179,0:10:27.239 like render the site. 0:10:27.239,0:10:30.059 And so this might remind you of new Twitter. 0:10:30.059,0:10:32.749 So Twitter in like, 2010 I think released[br]this 0:10:32.749,0:10:35.230 new experience where they were claiming this,[br]exactly. They 0:10:35.230,0:10:36.739 were saying this is going to be much better 0:10:36.739,0:10:38.850 for our users because we can just sort of 0:10:38.850,0:10:42.170 like snap in a new Tweet when you click. 0:10:42.170,0:10:44.129 And they actually found that this was kind[br]of 0:10:44.129,0:10:46.129 costly. Like, sometimes it would take ten[br]seconds to 0:10:46.129,0:10:49.220 render a 140 character Tweet. Because you[br]had to 0:10:49.220,0:10:51.579 download like all these assets and then like[br]that 0:10:51.579,0:10:53.149 would sort of like boot up, spin up and 0:10:53.149,0:10:55.529 build the page. This isn't like an actually[br]good 0:10:55.529,0:10:57.689 experience for users, at least the first time[br]they 0:10:57.689,0:10:59.829 visit the page. It's actually pretty bad. 0:10:59.829,0:11:03.600 So it doesn't quite stack up great here. It 0:11:03.600,0:11:07.459 is DRY. It is not SEO friendly, though. Now, 0:11:07.459,0:11:09.809 there's some tricks to sort of, making it,[br]sort 0:11:09.809,0:11:11.549 of making it SEO friendly, but, you know,[br]for 0:11:11.549,0:11:13.239 the most part it's kind of hard to make 0:11:13.239,0:11:15.519 it, you know, allow your app to like serve 0:11:15.519,0:11:17.920 HTML to a crawler. Now if you're not building 0:11:17.920,0:11:20.189 a content site, maybe it doesn't matter. But,[br]you 0:11:20.189,0:11:21.989 know, my claim is this is pretty important[br]on 0:11:21.989,0:11:25.559 most websites. It's a thick client. You don't[br]get 0:11:25.559,0:11:27.610 to write mostly one language. Half of it's[br]JavaScript. 0:11:27.610,0:11:30.819 So, again, half point for Rails. 0:11:30.819,0:11:33.329 So the point that I am trying to make 0:11:33.329,0:11:36.209 here is that each of these things makes like 0:11:36.209,0:11:38.379 a key, key trade off that we can't live 0:11:38.379,0:11:40.779 without. So what are we actually going to[br]do 0:11:40.779,0:11:42.069 about this? 0:11:42.069,0:11:43.899 Well, now I'm gonna show you like a new 0:11:43.899,0:11:46.189 solution that, you know, maybe it's good,[br]maybe it's 0:11:46.189,0:11:51.290 not. And actually, this starts with a, sort[br]of 0:11:51.290,0:11:53.489 like, admission. So I kind of lied to you 0:11:53.489,0:11:56.410 before. I told you I built this app that 0:11:56.410,0:11:58.619 I was showing you before using render which[br]is 0:11:58.619,0:12:00.589 this like, node.js thing. But the truth is,[br]I 0:12:00.589,0:12:02.649 don't even know JavaScript. I don't even know[br]anything 0:12:02.649,0:12:05.290 about node.js. Render. I just read about it,[br]right. 0:12:05.290,0:12:09.160 I actually built this app using this new sort 0:12:09.160,0:12:12.799 of like technique slash library called Perspective. 0:12:12.799,0:12:15.069 So again, here's the same app. And just to 0:12:15.069,0:12:18.059 remind you, you can kind of click around here 0:12:18.059,0:12:20.799 and, you know, things just sort of load. And 0:12:20.799,0:12:22.540 this is a very simple example, but things[br]are 0:12:22.540,0:12:25.029 snapping in, you know, just the parts of the 0:12:25.029,0:12:27.749 page that are changing. Need to get changed.[br]And 0:12:27.749,0:12:29.939 you can sort like edit and save stuff. And 0:12:29.939,0:12:32.259 we're just sort of updating parts of the page 0:12:32.259,0:12:34.009 that need to change. 0:12:34.009,0:12:36.999 And so this is this perspectives thing, which[br]I'm 0:12:36.999,0:12:39.179 claiming is better, right. So let's see how[br]it 0:12:39.179,0:12:42.769 stacks up on the chart that I just made. 0:12:42.769,0:12:46.949 It's DRY. It's SEO-friendly. It's a thick[br]client. You 0:12:46.949,0:12:48.230 write mostly one lang- I think you see where 0:12:48.230,0:12:50.720 this is going. And it's Rails. So I checked 0:12:50.720,0:12:52.529 all the boxes in my own talk. This is 0:12:52.529,0:12:55.429 a key, key thing. You have to be able 0:12:55.429,0:12:57.049 to do this if you're gonna speak at RailsConf. 0:12:57.049,0:12:59.839 You gotta have a chart, checks all the boxes. 0:12:59.839,0:13:01.819 This is good. 0:13:01.819,0:13:05.619 So, you know, the key sort of thing here, 0:13:05.619,0:13:08.819 the key part of Perspectives, is that we want 0:13:08.819,0:13:11.949 to be able to share our templates between[br]the 0:13:11.949,0:13:13.920 client and the server. So like the server[br]should 0:13:13.920,0:13:16.119 be able to render full HTML. And the client 0:13:16.119,0:13:17.660 should be able to like receive JSON and like 0:13:17.660,0:13:18.999 render a template, right. This is sort of[br]the 0:13:18.999,0:13:21.100 appeal of something like render. 0:13:21.100,0:13:28.100 So, here, you know, let's, let's say we thought, 0:13:28.499,0:13:30.709 well maybe we can sort of share templates.[br]Maybe 0:13:30.709,0:13:32.899 we can share our existing erb templates. Those[br]are 0:13:32.899,0:13:35.009 pretty easy to write. So here's like a simple 0:13:35.009,0:13:36.939 erb template, right. We're just generating[br]like a link 0:13:36.939,0:13:38.649 to a user. We're using the name as like 0:13:38.649,0:13:41.869 the anchor text. We're using user_url helper[br]from Rails 0:13:41.869,0:13:43.790 to like generate a link to it. This is 0:13:43.790,0:13:47.399 pretty simple. You might imagine that using[br]something like 0:13:47.399,0:13:50.669 Opal, which transforms Ruby in JavaScript,[br]you could like 0:13:50.669,0:13:53.389 pour it your whole server, kind of like, instance, 0:13:53.389,0:13:56.809 including all these helpers link link_to and[br]user_url, to 0:13:56.809,0:13:58.910 JavaScript, and then you could just jump down[br]your 0:13:58.910,0:14:01.029 erb template and then that could get sort[br]of 0:14:01.029,0:14:02.579 rendered on the client. 0:14:02.579,0:14:04.410 This might, you know, you might think that[br]this 0:14:04.410,0:14:06.959 works. But, actually, you can kind of do more 0:14:06.959,0:14:09.309 stuff in erb than you might sort of be 0:14:09.309,0:14:11.730 aware of from simple examples. Like, you can,[br]here's 0:14:11.730,0:14:13.720 an example, where I'm actually just running[br]like a 0:14:13.720,0:14:16.529 SQL query in an erb template. And this, I 0:14:16.529,0:14:21.509 think, demonstrates like, the fundamental[br]difference - yeah, boo! 0:14:21.509,0:14:24.779 This, I think, demonstrates like a fundamental[br]difference between, 0:14:24.779,0:14:27.549 you know, the client and the server, is that, 0:14:27.549,0:14:30.419 they're kind of in different environments.[br]Like, the server 0:14:30.419,0:14:33.149 has access to resources that the client, not[br]only 0:14:33.149,0:14:35.329 doesn't have access to but shouldn't have[br]access to. 0:14:35.329,0:14:37.609 The client should not ever be able to like 0:14:37.609,0:14:39.609 hook up to the database and ask some questions. 0:14:39.609,0:14:42.179 Right, so. And the client is the same. Like, 0:14:42.179,0:14:44.339 the client knows stuff about the user's browser.[br]Like, 0:14:44.339,0:14:46.660 they can inspect local storage and all this[br]stuff. 0:14:46.660,0:14:49.739 Like, they're fundamentally different environments.[br]And so I don't 0:14:49.739,0:14:52.279 think that any of the existing templates out[br]there 0:14:52.279,0:14:54.629 really get you this sort of shared environment[br]for 0:14:54.629,0:14:55.850 free. 0:14:55.850,0:14:59.850 So, the way, you know, so the way to 0:14:59.850,0:15:02.879 get to a shared template between a client[br]and 0:15:02.879,0:15:05.459 a server is to find the lowest common denominator. 0:15:05.459,0:15:08.259 So, like, if you've taken, you know, calculus[br]at 0:15:08.259,0:15:10.209 the graduate level, you might have heard of[br]the 0:15:10.209,0:15:13.639 lowest common denominator. It's the way that[br]you are 0:15:13.639,0:15:16.329 able to like, if you're trying to add fractions, 0:15:16.329,0:15:18.669 you can like, multiply the denominator- 0:15:18.669,0:15:20.850 The point is, it allows you to like find 0:15:20.850,0:15:24.519 some common ground between, you know, the[br]client and 0:15:24.519,0:15:28.160 the server, right. So we need lowest common[br]denominator. 0:15:28.160,0:15:30.389 Which is the dumbest possible template. So[br]we need 0:15:30.389,0:15:32.939 something that's really dumb, that has, that[br]basically can't 0:15:32.939,0:15:36.239 do anything. And so what is that? Well, that's 0:15:36.239,0:15:39.399 mustache. Mustache are the dumbest templates[br]out there. Don't 0:15:39.399,0:15:40.669 tell them I said that. They're probably in[br]the 0:15:40.669,0:15:43.399 other room or something. But they're, they're[br]pretty dumb. 0:15:43.399,0:15:46.979 You know, you might have heard mustache templates[br]referred 0:15:46.979,0:15:49.919 to as being logic-less. I actually think logic-less[br]is 0:15:49.919,0:15:51.669 kind of like a bad way of describing it. 0:15:51.669,0:15:53.919 Because when I hear logic-less, I'm kind of[br]thinking, 0:15:53.919,0:15:55.899 like, OK, I can't write like an if statement. 0:15:55.899,0:15:58.850 There's probably no like for loop situation.[br]Like, what 0:15:58.850,0:15:59.859 else can't I do? Well I probably can't do 0:15:59.859,0:16:02.329 like an if-else, like, you know, the reality[br]is 0:16:02.329,0:16:04.339 you can actually kind of do that stuff. It's 0:16:04.339,0:16:06.199 called a different thing. So I don't like[br]using 0:16:06.199,0:16:07.509 the word logic-less. 0:16:07.509,0:16:09.609 It's more like you can't run arbitrary code.[br]It's 0:16:09.609,0:16:13.069 more like no code, code-less or something.[br]So you 0:16:13.069,0:16:15.040 can't run arbitrary code. This is the sort[br]of 0:16:15.040,0:16:18.049 take away from mustache, right. And so, you[br]know, 0:16:18.049,0:16:20.199 this is kind of cool because, because you[br]can't 0:16:20.199,0:16:23.529 run arbitrary code, we can write mustache[br]template renders 0:16:23.529,0:16:26.350 in all these different languages. So you can[br]easily 0:16:26.350,0:16:29.829 render mustache templates in Ruby or JavaScript.[br]If you 0:16:29.829,0:16:31.489 want to use one of these other languages,[br]these 0:16:31.489,0:16:33.329 are terrible, but I guess you could use like 0:16:33.329,0:16:35.069 dot net or something if you wanted to render 0:16:35.069,0:16:37.619 a mustache template in dot net. I don't know 0:16:37.619,0:16:38.619 what you're doing but you might be able to 0:16:38.619,0:16:40.009 do that. 0:16:40.009,0:16:42.489 So, to show you like how to create a 0:16:42.489,0:16:43.839 mustache template, I want to look at like[br]a 0:16:43.839,0:16:46.869 specific example. So here's, like, the RailsGenius[br]app, and, 0:16:46.869,0:16:49.369 you know, in the left, lower left-hand corner[br]here 0:16:49.369,0:16:52.160 there's like an annotation, right. So this[br]is sort 0:16:52.160,0:16:55.619 of annotating the line node.js. And if we[br]sort 0:16:55.619,0:16:57.449 of zoom in on this thing, we can see 0:16:57.449,0:16:59.660 there are a few different components. 0:16:59.660,0:17:02.549 There's the section of text that's annotated.[br]So we'll 0:17:02.549,0:17:04.549 call that the referent. This is like a fancy 0:17:04.549,0:17:07.309 word for like reference or something. So we'll[br]call 0:17:07.309,0:17:09.660 that the referent. That's the line that I[br]highlighted 0:17:09.660,0:17:12.160 and explained. And then we'll call this the[br]sort 0:17:12.160,0:17:15.059 of body. And you'll notice the body can contain 0:17:15.059,0:17:17.959 like arbitrary HTML. There's a link to node.js[br]dot 0:17:17.959,0:17:20.099 org. A link to Ruby on Rails, et cetera. 0:17:20.099,0:17:22.490 I'm sort of adding, like, you know, I'm adding 0:17:22.490,0:17:25.459 hyper media here because it's the web. 0:17:25.459,0:17:26.829 And then there's this edit link, right. And[br]so 0:17:26.829,0:17:28.860 this edit link, you might imagine, should[br]appear for 0:17:28.860,0:17:31.880 some users and not others depending on, like,[br]what 0:17:31.880,0:17:34.559 your permissions are or what your sort of[br]situation 0:17:34.559,0:17:36.690 is. 0:17:36.690,0:17:39.659 And so mustache, the, the template for this,[br]the 0:17:39.659,0:17:42.230 whole template, looks like this. So I'm gonna[br]go 0:17:42.230,0:17:44.070 into like the specifics of how I would actually, 0:17:44.070,0:17:46.389 you know, what this is doing. But here's the 0:17:46.389,0:17:48.950 template. And to render this, I just need[br]this 0:17:48.950,0:17:51.639 hash of JSON data. So I can render this 0:17:51.639,0:17:53.759 anywhere as long as I have this hash. Key 0:17:53.759,0:17:55.850 thing to remember. 0:17:55.850,0:18:00.600 So, if I can't run code in mustache, like 0:18:00.600,0:18:03.610 I can run code in erb, how do I 0:18:03.610,0:18:06.039 actually like put data in the markup, which[br]is 0:18:06.039,0:18:09.009 like the whole point of templates, right? 0:18:09.009,0:18:11.299 So you can use these tags. Right, so given 0:18:11.299,0:18:14.840 this section of JSON, you have a referent[br]mapping 0:18:14.840,0:18:18.139 to node dot js, right. We can render that 0:18:18.139,0:18:21.029 data into this template with a, you know,[br]inside 0:18:21.029,0:18:23.130 of a block quote, by using this double curly 0:18:23.130,0:18:26.230 brace thing. This just says, like, basically,[br]gsub, or 0:18:26.230,0:18:29.269 actually not gsub, sub this referant into,[br]inside this 0:18:29.269,0:18:30.710 block quote. Pretty simple. 0:18:30.710,0:18:32.269 So this is just gonna print like block quote 0:18:32.269,0:18:37.220 node.js, you know. That should hopefully be[br]fairly self-evident. 0:18:37.220,0:18:39.409 So if you want to sort of do something 0:18:39.409,0:18:41.850 where you're printing raw HTML, the double[br]brace will 0:18:41.850,0:18:44.279 actually escape it. So that's most the time[br]what 0:18:44.279,0:18:46.389 you want. But in this case we're actually[br]like, 0:18:46.389,0:18:49.610 you know, we want hyper media in that annotation. 0:18:49.610,0:18:51.830 So this, you know, actually has an href. An 0:18:51.830,0:18:52.690 a tag, rather. 0:18:52.690,0:18:55.440 So we're gonna use the triple brace, which[br]is 0:18:55.440,0:18:57.470 another type of tag that says print this HTML 0:18:57.470,0:19:00.149 raw. So this will actually print out, like,[br]you 0:19:00.149,0:19:02.779 know, real anchor tag. Which is, in this case, 0:19:02.779,0:19:05.559 what we want. So here is the sort of 0:19:05.559,0:19:07.600 meat of mustache. This is probably the trickiest[br]part 0:19:07.600,0:19:10.399 of mustache. There's another type of tag which[br]is 0:19:10.399,0:19:13.990 this sort of double brace hash block, right. 0:19:13.990,0:19:16.960 So here is the block that I'm talking about. 0:19:16.960,0:19:18.330 So you can see this double brace, and then 0:19:18.330,0:19:20.820 there's hash edit. This hash is kind of where 0:19:20.820,0:19:23.080 the logic by another name comes into play[br]in 0:19:23.080,0:19:25.610 mustache. So this is going to, if edit is 0:19:25.610,0:19:27.880 like, a boolean type thing, it's going to[br]run, 0:19:27.880,0:19:30.370 or, or go into the block. If edit is 0:19:30.370,0:19:33.639 true, if edit is like a list of something, 0:19:33.639,0:19:35.340 it basically is your for loop is the way 0:19:35.340,0:19:36.610 to think about it. 0:19:36.610,0:19:37.960 There's one more thing that is like if edit 0:19:37.960,0:19:40.190 is like a hash, it kind of just will 0:19:40.190,0:19:44.409 run the intersection if the hash is there.[br]Otherwise 0:19:44.409,0:19:46.570 it won't. So in this case, we're just saying, 0:19:46.570,0:19:48.220 you know, we should show the edit link. That's 0:19:48.220,0:19:50.259 what edit true means. This is our logic by 0:19:50.259,0:19:54.110 another name. And then we're actually, you[br]know, grabbing 0:19:54.110,0:19:57.340 the edit href from the JSON hash as well. 0:19:57.340,0:19:59.009 And so this will result in just putting the, 0:19:59.009,0:20:00.139 printing the edit link. 0:20:00.139,0:20:03.090 Now if edit were false, it wouldn't print[br]that. 0:20:03.090,0:20:04.830 And so you might be asking, like, well what 0:20:04.830,0:20:06.330 if I wanted to do something else. Like I'm 0:20:06.330,0:20:09.860 used to writing these if-else statements.[br]So mustache also 0:20:09.860,0:20:12.970 has this other sort of tag, which is a 0:20:12.970,0:20:16.750 carrot. SO there's like double, double squiggly,[br]double curly 0:20:16.750,0:20:19.440 brace, carot edit, which just means sort of[br]go 0:20:19.440,0:20:22.519 into this block if edit is unset or false. 0:20:22.519,0:20:25.019 So this is the kind of last tag. So 0:20:25.019,0:20:27.070 in this case, if edit were false, we would 0:20:27.070,0:20:29.970 just print can't edit. So this is mustache.[br]That's 0:20:29.970,0:20:32.070 basically all you can do. 0:20:32.070,0:20:34.779 So how does this actually help us? Well, I 0:20:34.779,0:20:36.720 don't know if you guys remember, but at the 0:20:36.720,0:20:40.230 beginning of this mustache section, I showed[br]you this 0:20:40.230,0:20:42.519 template and I said all you need to render 0:20:42.519,0:20:44.980 this template is this hash. And I also told 0:20:44.980,0:20:47.090 you that there's a Ruby library for this and 0:20:47.090,0:20:48.779 a JavaScript library for this. 0:20:48.779,0:20:49.710 So I think you might see where this is 0:20:49.710,0:20:51.850 going. If we have some way of generating like 0:20:51.850,0:20:54.549 a hash, anywhere, then we can render it, we 0:20:54.549,0:20:57.070 can ship the template and the hash to any 0:20:57.070,0:21:00.110 environment and like render it there. 0:21:00.110,0:21:01.409 That's the point I'm trying to make. So how 0:21:01.409,0:21:03.809 do we actually generate this hash? That's[br]the sort 0:21:03.809,0:21:05.639 of tricky part. Well I'm gonna do some handwaving 0:21:05.639,0:21:08.080 here and say, well, this, Perspective's library[br]might help 0:21:08.080,0:21:10.289 us a little bit. 0:21:10.289,0:21:12.809 So you know here's a traditional Rails view.[br]This 0:21:12.809,0:21:15.789 is like an erb template, right. And so what 0:21:15.789,0:21:17.940 I'm saying is that if we split this into 0:21:17.940,0:21:21.610 a template, which is mustache, and a perspective,[br]which 0:21:21.610,0:21:25.009 is something, it's a new type of object, then 0:21:25.009,0:21:27.299 we can just have this data transport thing,[br]which 0:21:27.299,0:21:29.220 is just the hash, which is generated by the 0:21:29.220,0:21:32.490 perspective. And then we can render the template[br]anywhere. 0:21:32.490,0:21:33.750 So this is how we render on the client 0:21:33.750,0:21:35.610 or the server. 0:21:35.610,0:21:37.750 So what is this perspective thing look like?[br]Well, 0:21:37.750,0:21:40.289 as you might imagine, it's a bunch of stuff 0:21:40.289,0:21:44.370 that specifies what is in the hash. So, here's 0:21:44.370,0:21:46.539 the whole perspective. I'm gonna dive into[br]different parts 0:21:46.539,0:21:48.580 of it. But you can see it's just basically 0:21:48.580,0:21:50.710 a Ruby object with like some macros thrown[br]in. 0:21:50.710,0:21:52.470 That's, that's sort of the goal of the library. 0:21:52.470,0:21:55.509 It should just be a Ruby object. Plain Ruby 0:21:55.509,0:21:56.529 object. 0:21:56.529,0:21:59.840 So you can specify inputs, which you specify[br]with 0:21:59.840,0:22:02.779 params. So you can say param annotation, this[br]perspective 0:22:02.779,0:22:07.870 expects an annotation as input. You can specify[br]outputs. 0:22:07.870,0:22:12.330 This perspective outputs reference, which[br]is the annotation's referent 0:22:12.330,0:22:16.279 property. It also specifies body as a key.[br]And 0:22:16.279,0:22:18.509 that's the annotation's body as HTML. So this[br]is 0:22:18.509,0:22:20.029 gonna be raw HTML. 0:22:20.029,0:22:24.039 And so properties our output. And so these[br]are 0:22:24.039,0:22:26.799 actually just keys in this hash. So we can 0:22:26.799,0:22:30.929 just turn this perspective object into a JSON[br]object 0:22:30.929,0:22:32.960 and then that can be rendered anywhere. So[br]now 0:22:32.960,0:22:35.690 that we know what this perspective object[br]is, it 0:22:35.690,0:22:37.940 should be pretty self-explanatory how we get[br]from the 0:22:37.940,0:22:40.529 right over to the left and render this template. 0:22:40.529,0:22:42.590 Now you might be thinking, isn't this just[br]like 0:22:42.590,0:22:45.649 a fancy version of like helpers or something?[br]Like, 0:22:45.649,0:22:48.750 helpers with like a namespace? And it's actually[br]different 0:22:48.750,0:22:52.139 because, you know, helpers are sort of operating[br]at, 0:22:52.139,0:22:54.129 they seem like they kind of live in their 0:22:54.129,0:22:57.379 own separate object, like annotations' helper[br]or something. But 0:22:57.379,0:22:59.909 actually they're in a global namespace which[br]can be 0:22:59.909,0:23:02.029 called from any template at any time. And[br]so 0:23:02.029,0:23:04.159 they can kind of like override each other. 0:23:04.159,0:23:06.809 They also are direct function indication.[br]So this is 0:23:06.809,0:23:09.100 just data. This hash in the middle is just 0:23:09.100,0:23:12.070 data. SO like if you reference a property[br]twice, 0:23:12.070,0:23:14.240 you're always gonna get the same value, unlike[br]a 0:23:14.240,0:23:16.590 helper, which could theoretically return different[br]things if you 0:23:16.590,0:23:18.620 call it different times. SO it's kind of like 0:23:18.620,0:23:22.460 a safer thing for us as developers. 0:23:22.460,0:23:25.429 And so to build like an app with this, 0:23:25.429,0:23:27.649 you can imagine the initial request that the[br]client 0:23:27.649,0:23:30.879 makes will receive HTML so the, the server[br]will 0:23:30.879,0:23:33.669 say, OK let me take this perspective thing,[br]turn 0:23:33.669,0:23:35.919 it into JSON, render in mustache template[br]and then 0:23:35.919,0:23:37.870 send that back to the user. And, in the 0:23:37.870,0:23:39.659 case of like new Twitter, the user would just 0:23:39.659,0:23:42.179 see the 140 character Tweet rendered. And[br]in the 0:23:42.179,0:23:45.240 case of like a web-crawler for a search engine, 0:23:45.240,0:23:46.509 it would see like the full HTML that it 0:23:46.509,0:23:47.799 can then index. 0:23:47.799,0:23:50.019 And then subsequent requests, just like we[br]would do 0:23:50.019,0:23:52.330 with like Ember or Backbone or whatever, we[br]just 0:23:52.330,0:23:54.570 request JSON from the server and then we render 0:23:54.570,0:23:58.519 the part of the page that needs to change. 0:23:58.519,0:24:02.080 So, you the know, the key thing here I 0:24:02.080,0:24:05.659 think is that HTML is unstructured data. And[br]so 0:24:05.659,0:24:08.049 a lot of like sort of Rails patterns will 0:24:08.049,0:24:10.620 tell you just return like the snippet of HTML 0:24:10.620,0:24:12.889 from the server that you need and then snap 0:24:12.889,0:24:15.809 that in somewhere. And the eventually leads[br]to like 0:24:15.809,0:24:20.090 soupy code and coupling to like classes on[br]HTML 0:24:20.090,0:24:21.929 elements, which leads to a lot of like weirdo 0:24:21.929,0:24:24.049 bugs that are hard to track down. 0:24:24.049,0:24:26.830 JSON, on the other hand, is structured data.[br]It's 0:24:26.830,0:24:29.279 a lot easier to deal with this, so, you 0:24:29.279,0:24:31.350 can either render it or you could do something, 0:24:31.350,0:24:33.809 you know, on the client that's a little fancier. 0:24:33.809,0:24:35.360 If you want to do, update different parts[br]of 0:24:35.360,0:24:37.649 the page, whatever. The point is that it's[br]structured 0:24:37.649,0:24:39.470 and it's easy to deal with. And if you're 0:24:39.470,0:24:43.120 building out like a thick client, you want[br]to 0:24:43.120,0:24:47.769 couple your client experience to structured[br]data, not unstructured 0:24:47.769,0:24:48.659 data. 0:24:48.659,0:24:51.779 All right, so I'm gonna do the quick getting 0:24:51.779,0:24:53.299 started. You know this is, this is sort of 0:24:53.299,0:24:54.830 about this library, but I don't want it to 0:24:54.830,0:24:56.490 be all about this library. So, you know, it's 0:24:56.490,0:24:58.809 just a gem. You can just generate the install 0:24:58.809,0:25:01.929 for it. That'll like make your app perspectivified.[br]You 0:25:01.929,0:25:05.220 can scaffold stuff. You know, you break your[br]erb 0:25:05.220,0:25:10.309 templates into mustache templates and a perspective.[br]And you 0:25:10.309,0:25:13.259 just add this one line to your controller,[br]so 0:25:13.259,0:25:15.029 this just uses a responder to figure out if 0:25:15.029,0:25:18.120 the client wants HTML or wants JSON, and turns 0:25:18.120,0:25:19.840 the perspective into whatever you want to.[br]In this 0:25:19.840,0:25:22.710 case, it's just, you know, find this annotation[br]by 0:25:22.710,0:25:26.090 ID. Use this little macro to create your perspective 0:25:26.090,0:25:27.769 and pass it the data it needs, which in 0:25:27.769,0:25:29.659 this case is like an annotation. And then[br]we 0:25:29.659,0:25:33.649 can render a JSON version or an HTML version. 0:25:33.649,0:25:37.710 So what else does this buy us? So clearly 0:25:37.710,0:25:39.639 this rendering on the client and server thing[br]is 0:25:39.639,0:25:43.320 pretty good. But actually, I didn't like set[br]out, 0:25:43.320,0:25:45.120 when I was thinking about this, to like build 0:25:45.120,0:25:47.399 some sort of like new thick client like framework 0:25:47.399,0:25:49.600 thing that competes with Ember. That wasn't[br]my goal 0:25:49.600,0:25:52.879 and I'm still not sure that's my goal. The 0:25:52.879,0:25:54.509 benefits I'm about to tell you about were[br]actually 0:25:54.509,0:25:57.139 like the initial inspiration for like wanting[br]to build 0:25:57.139,0:25:58.139 this library. 0:25:58.139,0:26:02.909 So, number one is separation of concerns.[br]So, I 0:26:02.909,0:26:06.860 really hate seeing erb templates like this.[br]Here's like 0:26:06.860,0:26:08.649 an erb version of the template I just showed 0:26:08.649,0:26:10.679 you. So instead of having like a nice edit 0:26:10.679,0:26:14.200 property, there's often like some logic in[br]here, if 0:26:14.200,0:26:17.389 you look at the bottom there, that's checking,[br]like, 0:26:17.389,0:26:18.970 whether or not to show the edit link. And 0:26:18.970,0:26:20.730 this is kind of ugly. It's kind of ugly 0:26:20.730,0:26:23.240 no matter where it lives. But it's especially[br]ugly 0:26:23.240,0:26:24.519 if it lives in a template. 0:26:24.519,0:26:26.059 And it is so easy to do this with 0:26:26.059,0:26:29.120 erb, cause, you know, erb literally just means[br]embedded 0:26:29.120,0:26:31.509 Ruby. So you can just write anything. Like[br]I, 0:26:31.509,0:26:33.610 like I've seen saying. SO like here we're[br]saying, 0:26:33.610,0:26:36.509 the person can edit the annotation if they[br]created 0:26:36.509,0:26:39.379 or they're like a super admin type, type,[br]type 0:26:39.379,0:26:41.929 user. 0:26:41.929,0:26:47.419 So, mustache and perspectives force you into[br]this separation 0:26:47.419,0:26:49.850 of concerns, where you literally can't write[br]any code 0:26:49.850,0:26:51.789 in your template. So you have to put it 0:26:51.789,0:26:54.110 in the perspective, which is just a Ruby object, 0:26:54.110,0:26:56.090 which is where it kind of belongs. And there's 0:26:56.090,0:26:59.600 no, there's no love for this in erb land 0:26:59.600,0:27:01.490 in Rails. You're kind of, you're kind of off 0:27:01.490,0:27:03.370 in this waste land of like, I guess I'll 0:27:03.370,0:27:05.360 throw some view logic in here. I don't really 0:27:05.360,0:27:07.580 know where it's supposed to go. 0:27:07.580,0:27:08.970 And so this, this leads me to like, so 0:27:08.970,0:27:11.440 here's the, sorry, here's the perspective[br]version of it, 0:27:11.440,0:27:14.029 where actually just generate this edit property[br]and say 0:27:14.029,0:27:15.889 whether or not we want to display the link, 0:27:15.889,0:27:19.460 based on that logic I showed you before. 0:27:19.460,0:27:20.799 So this also gives you like, testing. So I 0:27:20.799,0:27:22.830 now DHH was like, you know, shitting on this 0:27:22.830,0:27:26.230 in his talk. I still think testing is important. 0:27:26.230,0:27:28.179 Maybe not TDD. But like the point is, if 0:27:28.179,0:27:30.720 you wanted to test like an erb template and 0:27:30.720,0:27:33.200 had some logic in this, in it, you would 0:27:33.200,0:27:34.820 have to like, render, the only thing you can 0:27:34.820,0:27:36.730 do is render the template. You can't talk[br]to 0:27:36.730,0:27:38.200 it. It's not an object. You can't ask it 0:27:38.200,0:27:40.320 questions. All you can do is render it and 0:27:40.320,0:27:41.990 then do like a string-match on it. 0:27:41.990,0:27:43.169 And in fact, I've seen a ton of tests 0:27:43.169,0:27:45.929 like this. Web driver tests are basically[br]just doing 0:27:45.929,0:27:48.320 like, advanced regexes to like figure out[br]if the 0:27:48.320,0:27:51.490 logic is right. And this is really bad. A 0:27:51.490,0:27:53.869 perspective is just a freakin' object. Like[br]you just 0:27:53.869,0:27:55.690 new it up and pass it the data it 0:27:55.690,0:27:57.779 needs and then you can test your logic. SO 0:27:57.779,0:28:00.009 here I'm just creating a test double. You[br]know, 0:28:00.009,0:28:02.450 test doubles are important in testing. Test[br]double for 0:28:02.450,0:28:04.950 a user, test double for an annotation. I'm[br]creating 0:28:04.950,0:28:07.899 this new perspective and then I'm asking it[br]if 0:28:07.899,0:28:10.399 the edit link is true and verifying that it 0:28:10.399,0:28:13.659 should be showing that. 0:28:13.659,0:28:16.659 So another thing is caching. So this is like 0:28:16.659,0:28:19.399 maybe a little bit difficult to motivate,[br]but like, 0:28:19.399,0:28:22.399 this sort of like cache digest thing, Russian[br]doll 0:28:22.399,0:28:23.789 caching thing is kind of hard for me to 0:28:23.789,0:28:25.950 like wrap my brain around, right. Like, you[br]have 0:28:25.950,0:28:27.850 to, you have to write, sometimes, like a special 0:28:27.850,0:28:30.429 comment to get the templates to know about[br]each 0:28:30.429,0:28:33.840 other. Not as good as just having objects[br]that 0:28:33.840,0:28:34.789 know about each other. 0:28:34.789,0:28:38.220 So if you want to cache an annotation show 0:28:38.220,0:28:40.450 perspective, you just use this cache macro[br]and that 0:28:40.450,0:28:44.429 says, use the annotation as the cache key,[br]right. 0:28:44.429,0:28:46.440 And so if you're familiar with, like, cache[br]keys 0:28:46.440,0:28:48.889 in Rails, if you're using generational caching,[br]this will 0:28:48.889,0:28:50.330 just say, the cache key - hopefully you can 0:28:50.330,0:28:52.600 see this - is just the type of object, 0:28:52.600,0:28:54.279 the id of the object, and when it was 0:28:54.279,0:28:55.139 last updated. 0:28:55.139,0:28:56.600 So this will like fall out of cache if 0:28:56.600,0:28:58.999 anyone updates the annotation or if it's like[br]a 0:28:58.999,0:29:00.980 different annotation it'll have a different[br]cache key. So 0:29:00.980,0:29:05.100 this sort of, hopefully this is, is somewhat[br]familiar. 0:29:05.100,0:29:07.240 If you have another template that you're rendering,[br]like 0:29:07.240,0:29:11.409 here, this annotation show perspective, is[br]rendering a nested 0:29:11.409,0:29:13.690 user slash avatar perspective, so you can[br]see that 0:29:13.690,0:29:16.340 at the bottom. You might want to say, well, 0:29:16.340,0:29:18.639 if the user updates their avatar, we also[br]want 0:29:18.639,0:29:19.700 this to fall out of cache. 0:29:19.700,0:29:22.169 This is sort of the, the Russian doll caching 0:29:22.169,0:29:24.629 of it all, right. So if the inside Russian 0:29:24.629,0:29:26.960 doll is uncached then it should bust the outside 0:29:26.960,0:29:30.179 Russian dolls cache key. So this thing, you[br]can 0:29:30.179,0:29:32.639 also assign a cache key to. You can say, 0:29:32.639,0:29:34.379 cache based on the user. So if the user 0:29:34.379,0:29:37.379 gets updated from the user's avatar perspective,[br]we want 0:29:37.379,0:29:39.960 this to fall out of cache. And so, like 0:29:39.960,0:29:41.549 I said, we want the whole thing to fall 0:29:41.549,0:29:43.659 out of cache if the user gets updated or 0:29:43.659,0:29:45.679 the annotation gets updated. 0:29:45.679,0:29:47.690 And so what perspective will do for you is 0:29:47.690,0:29:50.119 say, OK, we know that there's a nested user's 0:29:50.119,0:29:52.840 avatar perspective here, and so to generate[br]the cache 0:29:52.840,0:29:54.889 key for this whole thing, we're just going[br]to 0:29:54.889,0:29:57.929 concatenate the cache key from the annotation[br]and the 0:29:57.929,0:30:00.269 cache key from the user and produce this ugly, 0:30:00.269,0:30:02.090 terrible, long cache key, which you don't[br]have to 0:30:02.090,0:30:04.639 worry about at any point as the writer of 0:30:04.639,0:30:05.649 the code. 0:30:05.649,0:30:07.759 So this is all sort of handled transparently[br]for 0:30:07.759,0:30:12.249 you. So are we ready to sail off, to 0:30:12.249,0:30:14.980 drive off into the sunset in Rails land now 0:30:14.980,0:30:18.879 with this new stuff? Well, not quite. The,[br]the 0:30:18.879,0:30:21.499 point I'm trying to make here is that, or 0:30:21.499,0:30:22.529 one thing I want to get across here is 0:30:22.529,0:30:24.249 that this is sort of a nascent library slash 0:30:24.249,0:30:28.080 weekend project motivated by, you know, having,[br]making it 0:30:28.080,0:30:31.879 annoying to like, do caching, and it's hard[br]to 0:30:31.879,0:30:35.100 kind of separate your, your templates out,[br]and also 0:30:35.100,0:30:36.600 I'd like to be able to like render the 0:30:36.600,0:30:39.659 same thing on the client and server. But there's 0:30:39.659,0:30:41.100 still a bunch of stuff to be done, right. 0:30:41.100,0:30:42.840 Like there's still some work to be done to 0:30:42.840,0:30:45.590 like integrate this with existing like frontend[br]frameworks if 0:30:45.590,0:30:48.419 you want to add like a bunch more rich 0:30:48.419,0:30:50.700 experiences on the client. 0:30:50.700,0:30:53.600 And I want to get to the point, though, 0:30:53.600,0:30:55.549 where we can have a good answer to these 0:30:55.549,0:30:57.409 node.js libraries. Like this is a big motivation.[br]Like 0:30:57.409,0:31:00.110 I'm tired of node.js being, like, well let's[br]just 0:31:00.110,0:31:04.779 embrace JavaScript. Like, no let's not embrace[br]JavaScript. Ruby. 0:31:04.779,0:31:08.059 Ruby is better. So let's, let's get at them. 0:31:08.059,0:31:10.009 But, the key take away is you shouldn't be 0:31:10.009,0:31:12.499 sort of creating one version of your app that 0:31:12.499,0:31:14.110 lives on the server and one that lives on 0:31:14.110,0:31:17.299 the client. The ideal situation is move most[br]of 0:31:17.299,0:31:19.409 the stuff to the server but be able to 0:31:19.409,0:31:23.110 like still create this thick client situation. 0:31:23.110,0:31:25.440 So that's it. That's my talk. You can check 0:31:25.440,0:31:28.970 out this library by going to RapGenius slash[br]perspectives 0:31:28.970,0:31:31.139 on GitHub, or if you're lazy, there's this[br]bit.ly 0:31:31.139,0:31:34.039 link. bit.ly slash RG perspectives. And also,[br]as I 0:31:34.039,0:31:36.659 said at the beginning of the talk, we are 0:31:36.659,0:31:38.980 hiring. So if you're sort of interested in[br]this 0:31:38.980,0:31:41.809 kind of stuff or other stuff Rap Genius related, 0:31:41.809,0:31:43.149 get at me. Hit me up on Twitter. Hit 0:31:43.149,0:31:45.879 me up via email. Andy at RapGenius dot com. 0:31:45.879,0:31:48.199 And I think we have time for some questions.