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