[Script Info] Title: [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text Dialogue: 0,0:00:16.92,0:00:19.92,Default,,0000,0000,0000,,ANDREW WARNER: Welcome. I an Andrew Warner. Dialogue: 0,0:00:19.93,0:00:22.17,Default,,0000,0000,0000,,I am the director of engineering at Dialogue: 0,0:00:22.17,0:00:24.82,Default,,0000,0000,0000,,RapGenius dot com. You can follow me Dialogue: 0,0:00:24.82,0:00:28.09,Default,,0000,0000,0000,,on Twitter at wwarner. And you can also Dialogue: 0,0:00:28.09,0:00:30.71,Default,,0000,0000,0000,,follow RapGenius on Twitter at RapGenius. Dialogue: 0,0:00:30.71,0:00:32.60,Default,,0000,0000,0000,,So Tweet at me during the presentation, Dialogue: 0,0:00:32.60,0:00:34.69,Default,,0000,0000,0000,,after the presentation, tomorrow. Dialogue: 0,0:00:34.69,0:00:38.21,Default,,0000,0000,0000,,Whatever. I'm down. I will respond to your\Nstuff. Dialogue: 0,0:00:38.21,0:00:40.65,Default,,0000,0000,0000,,So, this is really exciting for me. This is Dialogue: 0,0:00:40.65,0:00:43.89,Default,,0000,0000,0000,,my first RailsConf speaking. And so, you know,\NI'm Dialogue: 0,0:00:43.89,0:00:47.97,Default,,0000,0000,0000,,super excited to be here. Come on. Little\Nround Dialogue: 0,0:00:47.97,0:00:50.47,Default,,0000,0000,0000,,of applause. Yeah. Yeah. Dialogue: 0,0:00:50.47,0:00:53.42,Default,,0000,0000,0000,,This is very exciting for me, not just because Dialogue: 0,0:00:53.42,0:00:55.68,Default,,0000,0000,0000,,I'm speaking, but also because you all, you\Nknow, Dialogue: 0,0:00:55.68,0:00:57.69,Default,,0000,0000,0000,,this is a pretty full room. You all chose Dialogue: 0,0:00:57.69,0:00:59.56,Default,,0000,0000,0000,,my talk over the other two talks! This is, Dialogue: 0,0:00:59.56,0:01:01.46,Default,,0000,0000,0000,,you know, it makes me feel good. It also Dialogue: 0,0:01:01.46,0:01:03.56,Default,,0000,0000,0000,,is crazy, because, how do you even know what Dialogue: 0,0:01:03.56,0:01:05.79,Default,,0000,0000,0000,,I'm gonna be talking about? I had some summary Dialogue: 0,0:01:05.79,0:01:07.54,Default,,0000,0000,0000,,that's kind of vague. Like, maybe I'm gonna\Nsay Dialogue: 0,0:01:07.54,0:01:09.36,Default,,0000,0000,0000,,some stuff, but, you know, maybe I'm gonna\Nchange Dialogue: 0,0:01:09.36,0:01:10.74,Default,,0000,0000,0000,,it a little bit. Now I've got this slide Dialogue: 0,0:01:10.74,0:01:12.50,Default,,0000,0000,0000,,on the screen that says Rails Holy Grail.\NWho Dialogue: 0,0:01:12.50,0:01:14.89,Default,,0000,0000,0000,,knows what that even means? So, you know,\NI'm Dialogue: 0,0:01:14.89,0:01:17.26,Default,,0000,0000,0000,,excited that you chose me even besides all\Nthis Dialogue: 0,0:01:17.26,0:01:17.56,Default,,0000,0000,0000,,stuff. Dialogue: 0,0:01:17.56,0:01:20.89,Default,,0000,0000,0000,,So, you know, I'm gonna be talking today about Dialogue: 0,0:01:20.89,0:01:22.50,Default,,0000,0000,0000,,the Rails Holy Grail. I'm a little bit disappointed Dialogue: 0,0:01:22.50,0:01:24.94,Default,,0000,0000,0000,,that DHH kind of stole my thunder with his Dialogue: 0,0:01:24.94,0:01:27.41,Default,,0000,0000,0000,,Holy Grail slide. But, you know, I, I still, Dialogue: 0,0:01:27.41,0:01:29.47,Default,,0000,0000,0000,,I'm gonna use it. I couldn't find another\Nreplacement Dialogue: 0,0:01:29.47,0:01:31.53,Default,,0000,0000,0000,,Holy Grail slide in the meantime. Dialogue: 0,0:01:31.53,0:01:33.89,Default,,0000,0000,0000,,So, I guess, what am I gonna be telling Dialogue: 0,0:01:33.89,0:01:36.53,Default,,0000,0000,0000,,you about? Well, first, I'm gonna be talking\Nto Dialogue: 0,0:01:36.53,0:01:38.50,Default,,0000,0000,0000,,you about what the Holy Grail is. So what Dialogue: 0,0:01:38.50,0:01:40.81,Default,,0000,0000,0000,,I mean when I say the Holy Grail. I'm Dialogue: 0,0:01:40.81,0:01:43.14,Default,,0000,0000,0000,,gonna be showing you some existing Rails solutions\Nthat Dialogue: 0,0:01:43.14,0:01:45.92,Default,,0000,0000,0000,,kind of get us close to this. I'm going Dialogue: 0,0:01:45.92,0:01:47.81,Default,,0000,0000,0000,,to be offering up a new solution for your Dialogue: 0,0:01:47.81,0:01:51.76,Default,,0000,0000,0000,,consideration today. And I'm gonna show you\Nwhat else Dialogue: 0,0:01:51.76,0:01:54.76,Default,,0000,0000,0000,,this new solution gets us. Dialogue: 0,0:01:54.76,0:01:58.71,Default,,0000,0000,0000,,So, first off, what is the Holy Grail of Dialogue: 0,0:01:58.71,0:02:01.08,Default,,0000,0000,0000,,the web? This background is like the song\NHoly Dialogue: 0,0:02:01.08,0:02:04.09,Default,,0000,0000,0000,,Grail by Jay-Z. I don't know. So, the Holy Dialogue: 0,0:02:04.09,0:02:06.01,Default,,0000,0000,0000,,Grail of the web, what I actually mean when Dialogue: 0,0:02:06.01,0:02:08.86,Default,,0000,0000,0000,,I say Holy Grail, is the best possible user Dialogue: 0,0:02:08.86,0:02:14.09,Default,,0000,0000,0000,,experience combined with the best possible\Ndeveloper experience. So Dialogue: 0,0:02:14.09,0:02:15.84,Default,,0000,0000,0000,,it should be very easy for me to rapidly Dialogue: 0,0:02:15.84,0:02:19.32,Default,,0000,0000,0000,,develop an application, as a developer, that\Nis also Dialogue: 0,0:02:19.32,0:02:22.75,Default,,0000,0000,0000,,easy to use for a user. Dialogue: 0,0:02:22.75,0:02:25.44,Default,,0000,0000,0000,,And so what is the best possible user experience? Dialogue: 0,0:02:25.44,0:02:28.73,Default,,0000,0000,0000,,Well, I'm talking about sort of a, a single-page Dialogue: 0,0:02:28.73,0:02:31.23,Default,,0000,0000,0000,,app thick client feel. So you shouldn't have\Nto Dialogue: 0,0:02:31.23,0:02:34.79,Default,,0000,0000,0000,,reload the entire page every time you, every\Ntime Dialogue: 0,0:02:34.79,0:02:37.28,Default,,0000,0000,0000,,the user actually clicks on a link. So in Dialogue: 0,0:02:37.28,0:02:39.33,Default,,0000,0000,0000,,2004, when Rails came out, it was really great Dialogue: 0,0:02:39.33,0:02:42.44,Default,,0000,0000,0000,,because it allowed you to create, very quickly,\Nwebsites Dialogue: 0,0:02:42.44,0:02:44.51,Default,,0000,0000,0000,,which were kind of a thin client, where every Dialogue: 0,0:02:44.51,0:02:46.35,Default,,0000,0000,0000,,single click reloaded the whole page. Dialogue: 0,0:02:46.35,0:02:48.46,Default,,0000,0000,0000,,And this was revolutionary. Before that, you\Nknow, it Dialogue: 0,0:02:48.46,0:02:51.26,Default,,0000,0000,0000,,was really difficult to make a site rapidly.\NAnd Dialogue: 0,0:02:51.26,0:02:54.19,Default,,0000,0000,0000,,around the same time, actually, Google released\Nthis Gmail Dialogue: 0,0:02:54.19,0:02:55.56,Default,,0000,0000,0000,,thing. Kind of hard to see the screenshot,\Nbut Dialogue: 0,0:02:55.56,0:02:58.63,Default,,0000,0000,0000,,I think you're all familiar with what Gmail\Nactually Dialogue: 0,0:02:58.63,0:03:01.96,Default,,0000,0000,0000,,is. Gmail was this single-page app where every\Nsingle Dialogue: 0,0:03:01.96,0:03:04.70,Default,,0000,0000,0000,,click actually loaded right on the same page\Nthat Dialogue: 0,0:03:04.70,0:03:06.61,Default,,0000,0000,0000,,you were on whatever you content you wanted\Nto Dialogue: 0,0:03:06.61,0:03:08.00,Default,,0000,0000,0000,,see as the user. You didn't have to wait Dialogue: 0,0:03:08.00,0:03:10.65,Default,,0000,0000,0000,,for your whole browser to refresh. This is\Npretty Dialogue: 0,0:03:10.65,0:03:13.09,Default,,0000,0000,0000,,good. So it's just no full page reloads at Dialogue: 0,0:03:13.09,0:03:15.07,Default,,0000,0000,0000,,all. This is the best experience for the user, Dialogue: 0,0:03:15.07,0:03:17.24,Default,,0000,0000,0000,,and it should sort of feel like a desktop Dialogue: 0,0:03:17.24,0:03:19.84,Default,,0000,0000,0000,,app or a mobile app in terms of the Dialogue: 0,0:03:19.84,0:03:21.45,Default,,0000,0000,0000,,native feel. Dialogue: 0,0:03:21.45,0:03:24.61,Default,,0000,0000,0000,,The best developer experience is a little\Nbit different. Dialogue: 0,0:03:24.61,0:03:26.88,Default,,0000,0000,0000,,So, you should be able to use a developer-friendly Dialogue: 0,0:03:26.88,0:03:28.65,Default,,0000,0000,0000,,framework. You should be able to rapidly develop\Nsomething. Dialogue: 0,0:03:28.65,0:03:31.86,Default,,0000,0000,0000,,You shouldn't have to reinvent the wheel.\NEasy things Dialogue: 0,0:03:31.86,0:03:34.35,Default,,0000,0000,0000,,should be easy. So, Ruby on Rails is one Dialogue: 0,0:03:34.35,0:03:36.03,Default,,0000,0000,0000,,of these frameworks. You might have heard\Nof this. Dialogue: 0,0:03:36.03,0:03:39.12,Default,,0000,0000,0000,,Kind of why we're here today. So you should Dialogue: 0,0:03:39.12,0:03:41.25,Default,,0000,0000,0000,,be able to use a developer-friendly framework. Dialogue: 0,0:03:41.25,0:03:43.72,Default,,0000,0000,0000,,You should be DRY. You shouldn't have to repeat Dialogue: 0,0:03:43.72,0:03:46.68,Default,,0000,0000,0000,,yourself. D-R-Y. Don't Repeat Yourself. But\Nactually, what I Dialogue: 0,0:03:46.68,0:03:49.16,Default,,0000,0000,0000,,mean here is more like DRV. So what is Dialogue: 0,0:03:49.16,0:03:52.13,Default,,0000,0000,0000,,DRV? Well, I mean, you shouldn't have to repeat Dialogue: 0,0:03:52.13,0:03:53.69,Default,,0000,0000,0000,,views. You shouldn't have to write one set\Nof Dialogue: 0,0:03:53.69,0:03:56.21,Default,,0000,0000,0000,,views that lives on the client's browser and\None Dialogue: 0,0:03:56.21,0:03:58.81,Default,,0000,0000,0000,,set of the views that lives on your web Dialogue: 0,0:03:58.81,0:04:00.44,Default,,0000,0000,0000,,server. Dialogue: 0,0:04:00.44,0:04:02.54,Default,,0000,0000,0000,,You should be writing mostly one language.\NAt least, Dialogue: 0,0:04:02.54,0:04:04.23,Default,,0000,0000,0000,,in so far as views are concerned. So you Dialogue: 0,0:04:04.23,0:04:06.85,Default,,0000,0000,0000,,shouldn't have to context switch. Context\Nswitching is very Dialogue: 0,0:04:06.85,0:04:09.55,Default,,0000,0000,0000,,expensive. Sort of switching from Ruby and\NRails to Dialogue: 0,0:04:09.55,0:04:13.07,Default,,0000,0000,0000,,JavaScript. This is difficult for us, as developers. Dialogue: 0,0:04:13.07,0:04:15.09,Default,,0000,0000,0000,,And your website should be SEO friendly. So\NI Dialogue: 0,0:04:15.09,0:04:17.81,Default,,0000,0000,0000,,guess this part really applies to content\Nsites. So Dialogue: 0,0:04:17.81,0:04:21.46,Default,,0000,0000,0000,,I work at RapGenius dot com. Content and SEO Dialogue: 0,0:04:21.46,0:04:23.87,Default,,0000,0000,0000,,friendliness is extremely important for us.\NWe lost a Dialogue: 0,0:04:23.87,0:04:26.30,Default,,0000,0000,0000,,bunch of traffic when we actually got banned\Nfrom Dialogue: 0,0:04:26.30,0:04:28.75,Default,,0000,0000,0000,,Google for a little while. They showed us\Nexactly Dialogue: 0,0:04:28.75,0:04:31.72,Default,,0000,0000,0000,,how important SEO was. So your site should\Nbe Dialogue: 0,0:04:31.72,0:04:35.28,Default,,0000,0000,0000,,able to show a crawler, a search engine crawler. Dialogue: 0,0:04:35.28,0:04:37.62,Default,,0000,0000,0000,,HTML that it can index and than make available Dialogue: 0,0:04:37.62,0:04:39.08,Default,,0000,0000,0000,,for users' searching. Dialogue: 0,0:04:39.08,0:04:42.09,Default,,0000,0000,0000,,So so what is the closest thing to this Dialogue: 0,0:04:42.09,0:04:44.56,Default,,0000,0000,0000,,Holy Grail today? Dialogue: 0,0:04:44.56,0:04:49.62,Default,,0000,0000,0000,,Well, it's kind of the node.js. There's a\Nnode.js Dialogue: 0,0:04:49.62,0:04:50.96,Default,,0000,0000,0000,,solution that I think is the best thing. Come Dialogue: 0,0:04:50.96,0:04:54.93,Default,,0000,0000,0000,,on, boo node.js! Give me some boos. Dialogue: 0,0:04:54.93,0:04:57.40,Default,,0000,0000,0000,,So there's this Airbnb Rendr framework, right.\NSo this Dialogue: 0,0:04:57.40,0:05:00.49,Default,,0000,0000,0000,,says render your backbone JS apps on the client Dialogue: 0,0:05:00.49,0:05:03.38,Default,,0000,0000,0000,,and on the server using node.js. So this framework Dialogue: 0,0:05:03.38,0:05:05.88,Default,,0000,0000,0000,,is, you know, pretty easy to use. You write Dialogue: 0,0:05:05.88,0:05:09.53,Default,,0000,0000,0000,,your backbone JS client-side app and the client\Ncan Dialogue: 0,0:05:09.53,0:05:11.38,Default,,0000,0000,0000,,sort of incrementally update the page and\Nthis sort Dialogue: 0,0:05:11.38,0:05:14.68,Default,,0000,0000,0000,,of Gmail-like experience. And then the server\Ncan also Dialogue: 0,0:05:14.68,0:05:18.97,Default,,0000,0000,0000,,render full HTML pages for arbitrarily deep\Nlinks. So Dialogue: 0,0:05:18.97,0:05:20.82,Default,,0000,0000,0000,,the user can still see a full HTML page Dialogue: 0,0:05:20.82,0:05:23.50,Default,,0000,0000,0000,,if they get deep-linked, and a web browser,\Nor Dialogue: 0,0:05:23.50,0:05:25.75,Default,,0000,0000,0000,,sorry, a web crawler for a search engine can Dialogue: 0,0:05:25.75,0:05:27.61,Default,,0000,0000,0000,,also see HTML. So this, I think, is the Dialogue: 0,0:05:27.61,0:05:29.94,Default,,0000,0000,0000,,best solution right there. Right, out there\Ntoday. Dialogue: 0,0:05:29.94,0:05:32.19,Default,,0000,0000,0000,,And here, I've actually built like a little\Ndemo Dialogue: 0,0:05:32.19,0:05:33.75,Default,,0000,0000,0000,,app using render to show you how cool it Dialogue: 0,0:05:33.75,0:05:35.88,Default,,0000,0000,0000,,is. So this is a little bit washed out. Dialogue: 0,0:05:35.88,0:05:37.95,Default,,0000,0000,0000,,But, this is sort of a mini version of Dialogue: 0,0:05:37.95,0:05:41.27,Default,,0000,0000,0000,,our site RapGenius. It's, so RapGenius allows\Nyou to Dialogue: 0,0:05:41.27,0:05:45.17,Default,,0000,0000,0000,,view documents and read documents and also\Nread inline Dialogue: 0,0:05:45.17,0:05:48.04,Default,,0000,0000,0000,,annotations on those documents. And the annotations\Nare meant Dialogue: 0,0:05:48.04,0:05:52.83,Default,,0000,0000,0000,,to provide context and also explanation, if\Nsomething's complicated, Dialogue: 0,0:05:52.83,0:05:54.37,Default,,0000,0000,0000,,and just add to the text. Dialogue: 0,0:05:54.37,0:05:56.97,Default,,0000,0000,0000,,So here I've built RailsGenius, which allows\Nyou to Dialogue: 0,0:05:56.97,0:06:01.17,Default,,0000,0000,0000,,add context to, like, Rails talk abstracts.\NSo this Dialogue: 0,0:06:01.17,0:06:04.22,Default,,0000,0000,0000,,is my talk. And I've added some inline annotations Dialogue: 0,0:06:04.22,0:06:05.37,Default,,0000,0000,0000,,here, and the, the point I'm trying to make Dialogue: 0,0:06:05.37,0:06:06.97,Default,,0000,0000,0000,,is that we should be able to, when I Dialogue: 0,0:06:06.97,0:06:09.36,Default,,0000,0000,0000,,click this link, to add views, which is actually Dialogue: 0,0:06:09.36,0:06:11.78,Default,,0000,0000,0000,,an annotation, this shouldn't refresh the\Nwhole page. It Dialogue: 0,0:06:11.78,0:06:13.53,Default,,0000,0000,0000,,should just load-in the part of the page that Dialogue: 0,0:06:13.53,0:06:15.76,Default,,0000,0000,0000,,changed. Which is a much better experience\Nfor the Dialogue: 0,0:06:15.76,0:06:16.25,Default,,0000,0000,0000,,user. Dialogue: 0,0:06:16.25,0:06:17.81,Default,,0000,0000,0000,,So if I actually click on this, it just Dialogue: 0,0:06:17.81,0:06:19.65,Default,,0000,0000,0000,,loads that part of the page. You know, this Dialogue: 0,0:06:19.65,0:06:21.43,Default,,0000,0000,0000,,is something that, you know, might be familiar\Nto Dialogue: 0,0:06:21.43,0:06:23.54,Default,,0000,0000,0000,,you from using apps, but it's, it's kind of Dialogue: 0,0:06:23.54,0:06:25.09,Default,,0000,0000,0000,,hard to like do this out of the box Dialogue: 0,0:06:25.09,0:06:27.24,Default,,0000,0000,0000,,in Rails. And, you know, also you should be Dialogue: 0,0:06:27.24,0:06:29.29,Default,,0000,0000,0000,,able to like edit it right there and that Dialogue: 0,0:06:29.29,0:06:31.57,Default,,0000,0000,0000,,should just snap in the edit view, et cetera. Dialogue: 0,0:06:31.57,0:06:33.52,Default,,0000,0000,0000,,And this should not be too, too difficult\Nto Dialogue: 0,0:06:33.52,0:06:36.71,Default,,0000,0000,0000,,build. Looks like I lost my internet connection.\NThere Dialogue: 0,0:06:36.71,0:06:38.22,Default,,0000,0000,0000,,we go. Dialogue: 0,0:06:38.22,0:06:40.97,Default,,0000,0000,0000,,So this kind of stacks up pretty well. It's Dialogue: 0,0:06:40.97,0:06:44.30,Default,,0000,0000,0000,,DRY. We have one set of views. It's SEO-friendly. Dialogue: 0,0:06:44.30,0:06:48.28,Default,,0000,0000,0000,,You know, we can serve HTML the crawlers.\NIt's Dialogue: 0,0:06:48.28,0:06:51.76,Default,,0000,0000,0000,,a thick-client feel, so single-page app. Mostly\Nwrite one Dialogue: 0,0:06:51.76,0:06:54.93,Default,,0000,0000,0000,,language. It's backbone JavaScript, et cetera.\NBut it is Dialogue: 0,0:06:54.93,0:06:57.19,Default,,0000,0000,0000,,not Rails. So I think it takes, it still Dialogue: 0,0:06:57.19,0:06:59.44,Default,,0000,0000,0000,,took me awhile, even with this render thing,\Nto Dialogue: 0,0:06:59.44,0:07:01.76,Default,,0000,0000,0000,,like, create an app that was good. And Rails Dialogue: 0,0:07:01.76,0:07:03.49,Default,,0000,0000,0000,,is just much easier to create like, the vanilla Dialogue: 0,0:07:03.49,0:07:06.41,Default,,0000,0000,0000,,example apps using, like, scaffolding or even\Nnot using Dialogue: 0,0:07:06.41,0:07:08.86,Default,,0000,0000,0000,,scaffolding. It's just way faster for development.\NSo I Dialogue: 0,0:07:08.86,0:07:10.39,Default,,0000,0000,0000,,still think this is bad even though it's the Dialogue: 0,0:07:10.39,0:07:12.70,Default,,0000,0000,0000,,closest thing to the Holy Grail today. Dialogue: 0,0:07:12.70,0:07:16.37,Default,,0000,0000,0000,,But, my point is that Rails, I'm, I'm worried, Dialogue: 0,0:07:16.37,0:07:17.78,Default,,0000,0000,0000,,because I think Rails is kind of getting left Dialogue: 0,0:07:17.78,0:07:19.42,Default,,0000,0000,0000,,in the dust in this respect. Like, it's kind Dialogue: 0,0:07:19.42,0:07:21.84,Default,,0000,0000,0000,,of, there's not really like an established\Nsolution for Dialogue: 0,0:07:21.84,0:07:25.86,Default,,0000,0000,0000,,building like a thick client good experience\NRails app. Dialogue: 0,0:07:25.86,0:07:29.04,Default,,0000,0000,0000,,And so now I'm gonna show you some sort Dialogue: 0,0:07:29.04,0:07:32.10,Default,,0000,0000,0000,,of solutions that get part way there. So let's Dialogue: 0,0:07:32.10,0:07:33.43,Default,,0000,0000,0000,,look at those. Dialogue: 0,0:07:33.43,0:07:35.56,Default,,0000,0000,0000,,So one option, and, you know, this is kind Dialogue: 0,0:07:35.56,0:07:36.86,Default,,0000,0000,0000,,of a joke but it's a serious thing that Dialogue: 0,0:07:36.86,0:07:39.52,Default,,0000,0000,0000,,people actually do, is creating one version\Nof your Dialogue: 0,0:07:39.52,0:07:42.01,Default,,0000,0000,0000,,app that lives on the client, and one version Dialogue: 0,0:07:42.01,0:07:43.93,Default,,0000,0000,0000,,of your app that lives on the server. And Dialogue: 0,0:07:43.93,0:07:45.76,Default,,0000,0000,0000,,so, you know, in this example you would write Dialogue: 0,0:07:45.76,0:07:48.29,Default,,0000,0000,0000,,erb or HAML on the server, and then you Dialogue: 0,0:07:48.29,0:07:50.33,Default,,0000,0000,0000,,would have an API that returns JSON from the Dialogue: 0,0:07:50.33,0:07:52.51,Default,,0000,0000,0000,,server to the client, and then the client\Nwould Dialogue: 0,0:07:52.51,0:07:54.36,Default,,0000,0000,0000,,figure out how to render new parts of the Dialogue: 0,0:07:54.36,0:07:56.13,Default,,0000,0000,0000,,page that it wants to snap in using like Dialogue: 0,0:07:56.13,0:07:59.74,Default,,0000,0000,0000,,some kind of frontend like handlebar or underscore.js\Ntemplates. Dialogue: 0,0:07:59.74,0:08:03.07,Default,,0000,0000,0000,,Right, so this seems kind of reasonable. But\Nthe Dialogue: 0,0:08:03.07,0:08:05.72,Default,,0000,0000,0000,,problem is if you forget to update both templates Dialogue: 0,0:08:05.72,0:08:07.41,Default,,0000,0000,0000,,at the same time, you're gonna end up with Dialogue: 0,0:08:07.41,0:08:09.82,Default,,0000,0000,0000,,some inconsistency between the client and\Nthe server in Dialogue: 0,0:08:09.82,0:08:12.02,Default,,0000,0000,0000,,terms of the logic. And this can be very, Dialogue: 0,0:08:12.02,0:08:13.87,Default,,0000,0000,0000,,very dangerous. It can lead to some hard to Dialogue: 0,0:08:13.87,0:08:16.62,Default,,0000,0000,0000,,suss out bugs and, you know, we all know Dialogue: 0,0:08:16.62,0:08:19.39,Default,,0000,0000,0000,,DRY is a good thing to strive towards. Dialogue: 0,0:08:19.39,0:08:21.25,Default,,0000,0000,0000,,So this doesn't stack up very well. It's not Dialogue: 0,0:08:21.25,0:08:25.68,Default,,0000,0000,0000,,DRY. It's SEO-friendly. It's a thick client.\NYou didn't Dialogue: 0,0:08:25.68,0:08:27.28,Default,,0000,0000,0000,,write mostly one language, though. You had\Nto write Dialogue: 0,0:08:27.28,0:08:28.70,Default,,0000,0000,0000,,a bunch of stuff on the client and the Dialogue: 0,0:08:28.70,0:08:31.15,Default,,0000,0000,0000,,server. And we only get a half point for Dialogue: 0,0:08:31.15,0:08:32.47,Default,,0000,0000,0000,,Rails. So you've gotta spend a lot of time Dialogue: 0,0:08:32.47,0:08:35.49,Default,,0000,0000,0000,,still on the frontend noodling around there. Dialogue: 0,0:08:35.49,0:08:38.69,Default,,0000,0000,0000,,All right. So Turbolinks are something you\Nalso might Dialogue: 0,0:08:38.69,0:08:39.95,Default,,0000,0000,0000,,have heard of. You might be thinking, well\NI Dialogue: 0,0:08:39.95,0:08:41.30,Default,,0000,0000,0000,,can just do this with Turbolinks. This is\Nlike Dialogue: 0,0:08:41.30,0:08:44.77,Default,,0000,0000,0000,,a one-liner, right? So Turbolinks, the way\Nit works, Dialogue: 0,0:08:44.77,0:08:46.88,Default,,0000,0000,0000,,is you write just one set of views, and Dialogue: 0,0:08:46.88,0:08:49.27,Default,,0000,0000,0000,,then when the user clicks on a link, you Dialogue: 0,0:08:49.27,0:08:50.75,Default,,0000,0000,0000,,can just pop in the whole new page but Dialogue: 0,0:08:50.75,0:08:52.91,Default,,0000,0000,0000,,save the browser instance. So you save on\Nthis Dialogue: 0,0:08:52.91,0:08:57.03,Default,,0000,0000,0000,,overhead of, like, parsing and compiling CSS\Nand interpreting Dialogue: 0,0:08:57.03,0:08:59.83,Default,,0000,0000,0000,,JavaScript and, you know, running all this\Nstuff. It, Dialogue: 0,0:08:59.83,0:09:01.36,Default,,0000,0000,0000,,it's actually kind of expensive to spin up\Na Dialogue: 0,0:09:01.36,0:09:04.20,Default,,0000,0000,0000,,browser instance for the client. So you, you\Neliminate Dialogue: 0,0:09:04.20,0:09:07.31,Default,,0000,0000,0000,,all that overhead and your client is extremely\Nsimple. Dialogue: 0,0:09:07.31,0:09:10.50,Default,,0000,0000,0000,,You basically have to write no JavaScript. Dialogue: 0,0:09:10.50,0:09:13.90,Default,,0000,0000,0000,,So the problem is that Turbolinks kind of\Nends Dialogue: 0,0:09:13.90,0:09:15.51,Default,,0000,0000,0000,,there. There's nowhere else to go. If you\Nwant Dialogue: 0,0:09:15.51,0:09:17.07,Default,,0000,0000,0000,,to snap in, like, just a new part of Dialogue: 0,0:09:17.07,0:09:19.22,Default,,0000,0000,0000,,the page, you've gotta write some kind of\Ncustom Dialogue: 0,0:09:19.22,0:09:21.75,Default,,0000,0000,0000,,controller action that just returns that part\Nof the Dialogue: 0,0:09:21.75,0:09:24.14,Default,,0000,0000,0000,,page and then you've gotta use like some jQuery Dialogue: 0,0:09:24.14,0:09:26.10,Default,,0000,0000,0000,,soup type thing to like snap that in and Dialogue: 0,0:09:26.10,0:09:28.84,Default,,0000,0000,0000,,then you're relying upon your, your page structure.\NSo Dialogue: 0,0:09:28.84,0:09:33.06,Default,,0000,0000,0000,,that is not a great solution. Dialogue: 0,0:09:33.06,0:09:34.58,Default,,0000,0000,0000,,But this works pretty well if you're trying\Nto Dialogue: 0,0:09:34.58,0:09:38.03,Default,,0000,0000,0000,,do, depending on what you're trying to do.\NSo, Dialogue: 0,0:09:38.03,0:09:41.80,Default,,0000,0000,0000,,you know, this is DRY. It is SEO-friendly.\NIt's Dialogue: 0,0:09:41.80,0:09:44.02,Default,,0000,0000,0000,,not really like a proper thick client, though.\NIt's Dialogue: 0,0:09:44.02,0:09:46.09,Default,,0000,0000,0000,,kind of like a fake thick client. Feels almost Dialogue: 0,0:09:46.09,0:09:48.49,Default,,0000,0000,0000,,like a thick client. Not quite there. Mostly\Nwrite Dialogue: 0,0:09:48.49,0:09:50.87,Default,,0000,0000,0000,,one language. We've got that covered. We've\Nalso got Dialogue: 0,0:09:50.87,0:09:53.05,Default,,0000,0000,0000,,Rails covered. So this is kind of why Turbolinks Dialogue: 0,0:09:53.05,0:09:55.34,Default,,0000,0000,0000,,is so popular I think. Because it basically\Ndoes Dialogue: 0,0:09:55.34,0:09:58.01,Default,,0000,0000,0000,,what you want without much hassle. Dialogue: 0,0:09:58.01,0:10:01.63,Default,,0000,0000,0000,,So there's also this Ember/Angular/Backbone\Ntype movement now. You Dialogue: 0,0:10:01.63,0:10:03.09,Default,,0000,0000,0000,,might have sort of seen, there are a bunch Dialogue: 0,0:10:03.09,0:10:05.07,Default,,0000,0000,0000,,of talks about this. People allude to it all Dialogue: 0,0:10:05.07,0:10:07.24,Default,,0000,0000,0000,,the time. This is sort of the new way, Dialogue: 0,0:10:07.24,0:10:09.51,Default,,0000,0000,0000,,this is the new wave of building Rails apps. Dialogue: 0,0:10:09.51,0:10:11.54,Default,,0000,0000,0000,,So you just have a JSON API in your Dialogue: 0,0:10:11.54,0:10:15.14,Default,,0000,0000,0000,,server, that's it. Your entire app experience\Nlives on Dialogue: 0,0:10:15.14,0:10:17.28,Default,,0000,0000,0000,,the client, so it lives in JavaScript or CoffeeScript, Dialogue: 0,0:10:17.28,0:10:20.15,Default,,0000,0000,0000,,what have you. And the initial page load,\Nthe Dialogue: 0,0:10:20.15,0:10:22.88,Default,,0000,0000,0000,,first time your user visits the site, they\Ndownload Dialogue: 0,0:10:22.88,0:10:24.69,Default,,0000,0000,0000,,like this whole JS app thing, and then that Dialogue: 0,0:10:24.69,0:10:26.18,Default,,0000,0000,0000,,sort of boots up and figures out how to Dialogue: 0,0:10:26.18,0:10:27.24,Default,,0000,0000,0000,,like render the site. Dialogue: 0,0:10:27.24,0:10:30.06,Default,,0000,0000,0000,,And so this might remind you of new Twitter. Dialogue: 0,0:10:30.06,0:10:32.75,Default,,0000,0000,0000,,So Twitter in like, 2010 I think released\Nthis Dialogue: 0,0:10:32.75,0:10:35.23,Default,,0000,0000,0000,,new experience where they were claiming this,\Nexactly. They Dialogue: 0,0:10:35.23,0:10:36.74,Default,,0000,0000,0000,,were saying this is going to be much better Dialogue: 0,0:10:36.74,0:10:38.85,Default,,0000,0000,0000,,for our users because we can just sort of Dialogue: 0,0:10:38.85,0:10:42.17,Default,,0000,0000,0000,,like snap in a new Tweet when you click. Dialogue: 0,0:10:42.17,0:10:44.13,Default,,0000,0000,0000,,And they actually found that this was kind\Nof Dialogue: 0,0:10:44.13,0:10:46.13,Default,,0000,0000,0000,,costly. Like, sometimes it would take ten\Nseconds to Dialogue: 0,0:10:46.13,0:10:49.22,Default,,0000,0000,0000,,render a 140 character Tweet. Because you\Nhad to Dialogue: 0,0:10:49.22,0:10:51.58,Default,,0000,0000,0000,,download like all these assets and then like\Nthat Dialogue: 0,0:10:51.58,0:10:53.15,Default,,0000,0000,0000,,would sort of like boot up, spin up and Dialogue: 0,0:10:53.15,0:10:55.53,Default,,0000,0000,0000,,build the page. This isn't like an actually\Ngood Dialogue: 0,0:10:55.53,0:10:57.69,Default,,0000,0000,0000,,experience for users, at least the first time\Nthey Dialogue: 0,0:10:57.69,0:10:59.83,Default,,0000,0000,0000,,visit the page. It's actually pretty bad. Dialogue: 0,0:10:59.83,0:11:03.60,Default,,0000,0000,0000,,So it doesn't quite stack up great here. It Dialogue: 0,0:11:03.60,0:11:07.46,Default,,0000,0000,0000,,is DRY. It is not SEO friendly, though. Now, Dialogue: 0,0:11:07.46,0:11:09.81,Default,,0000,0000,0000,,there's some tricks to sort of, making it,\Nsort Dialogue: 0,0:11:09.81,0:11:11.55,Default,,0000,0000,0000,,of making it SEO friendly, but, you know,\Nfor Dialogue: 0,0:11:11.55,0:11:13.24,Default,,0000,0000,0000,,the most part it's kind of hard to make Dialogue: 0,0:11:13.24,0:11:15.52,Default,,0000,0000,0000,,it, you know, allow your app to like serve Dialogue: 0,0:11:15.52,0:11:17.92,Default,,0000,0000,0000,,HTML to a crawler. Now if you're not building Dialogue: 0,0:11:17.92,0:11:20.19,Default,,0000,0000,0000,,a content site, maybe it doesn't matter. But,\Nyou Dialogue: 0,0:11:20.19,0:11:21.99,Default,,0000,0000,0000,,know, my claim is this is pretty important\Non Dialogue: 0,0:11:21.99,0:11:25.56,Default,,0000,0000,0000,,most websites. It's a thick client. You don't\Nget Dialogue: 0,0:11:25.56,0:11:27.61,Default,,0000,0000,0000,,to write mostly one language. Half of it's\NJavaScript. Dialogue: 0,0:11:27.61,0:11:30.82,Default,,0000,0000,0000,,So, again, half point for Rails. Dialogue: 0,0:11:30.82,0:11:33.33,Default,,0000,0000,0000,,So the point that I am trying to make Dialogue: 0,0:11:33.33,0:11:36.21,Default,,0000,0000,0000,,here is that each of these things makes like Dialogue: 0,0:11:36.21,0:11:38.38,Default,,0000,0000,0000,,a key, key trade off that we can't live Dialogue: 0,0:11:38.38,0:11:40.78,Default,,0000,0000,0000,,without. So what are we actually going to\Ndo Dialogue: 0,0:11:40.78,0:11:42.07,Default,,0000,0000,0000,,about this? Dialogue: 0,0:11:42.07,0:11:43.90,Default,,0000,0000,0000,,Well, now I'm gonna show you like a new Dialogue: 0,0:11:43.90,0:11:46.19,Default,,0000,0000,0000,,solution that, you know, maybe it's good,\Nmaybe it's Dialogue: 0,0:11:46.19,0:11:51.29,Default,,0000,0000,0000,,not. And actually, this starts with a, sort\Nof Dialogue: 0,0:11:51.29,0:11:53.49,Default,,0000,0000,0000,,like, admission. So I kind of lied to you Dialogue: 0,0:11:53.49,0:11:56.41,Default,,0000,0000,0000,,before. I told you I built this app that Dialogue: 0,0:11:56.41,0:11:58.62,Default,,0000,0000,0000,,I was showing you before using render which\Nis Dialogue: 0,0:11:58.62,0:12:00.59,Default,,0000,0000,0000,,this like, node.js thing. But the truth is,\NI Dialogue: 0,0:12:00.59,0:12:02.65,Default,,0000,0000,0000,,don't even know JavaScript. I don't even know\Nanything Dialogue: 0,0:12:02.65,0:12:05.29,Default,,0000,0000,0000,,about node.js. Render. I just read about it,\Nright. Dialogue: 0,0:12:05.29,0:12:09.16,Default,,0000,0000,0000,,I actually built this app using this new sort Dialogue: 0,0:12:09.16,0:12:12.80,Default,,0000,0000,0000,,of like technique slash library called Perspective. Dialogue: 0,0:12:12.80,0:12:15.07,Default,,0000,0000,0000,,So again, here's the same app. And just to Dialogue: 0,0:12:15.07,0:12:18.06,Default,,0000,0000,0000,,remind you, you can kind of click around here Dialogue: 0,0:12:18.06,0:12:20.80,Default,,0000,0000,0000,,and, you know, things just sort of load. And Dialogue: 0,0:12:20.80,0:12:22.54,Default,,0000,0000,0000,,this is a very simple example, but things\Nare Dialogue: 0,0:12:22.54,0:12:25.03,Default,,0000,0000,0000,,snapping in, you know, just the parts of the Dialogue: 0,0:12:25.03,0:12:27.75,Default,,0000,0000,0000,,page that are changing. Need to get changed.\NAnd Dialogue: 0,0:12:27.75,0:12:29.94,Default,,0000,0000,0000,,you can sort like edit and save stuff. And Dialogue: 0,0:12:29.94,0:12:32.26,Default,,0000,0000,0000,,we're just sort of updating parts of the page Dialogue: 0,0:12:32.26,0:12:34.01,Default,,0000,0000,0000,,that need to change. Dialogue: 0,0:12:34.01,0:12:36.100,Default,,0000,0000,0000,,And so this is this perspectives thing, which\NI'm Dialogue: 0,0:12:36.100,0:12:39.18,Default,,0000,0000,0000,,claiming is better, right. So let's see how\Nit Dialogue: 0,0:12:39.18,0:12:42.77,Default,,0000,0000,0000,,stacks up on the chart that I just made. Dialogue: 0,0:12:42.77,0:12:46.95,Default,,0000,0000,0000,,It's DRY. It's SEO-friendly. It's a thick\Nclient. You Dialogue: 0,0:12:46.95,0:12:48.23,Default,,0000,0000,0000,,write mostly one lang- I think you see where Dialogue: 0,0:12:48.23,0:12:50.72,Default,,0000,0000,0000,,this is going. And it's Rails. So I checked Dialogue: 0,0:12:50.72,0:12:52.53,Default,,0000,0000,0000,,all the boxes in my own talk. This is Dialogue: 0,0:12:52.53,0:12:55.43,Default,,0000,0000,0000,,a key, key thing. You have to be able Dialogue: 0,0:12:55.43,0:12:57.05,Default,,0000,0000,0000,,to do this if you're gonna speak at RailsConf. Dialogue: 0,0:12:57.05,0:12:59.84,Default,,0000,0000,0000,,You gotta have a chart, checks all the boxes. Dialogue: 0,0:12:59.84,0:13:01.82,Default,,0000,0000,0000,,This is good. Dialogue: 0,0:13:01.82,0:13:05.62,Default,,0000,0000,0000,,So, you know, the key sort of thing here, Dialogue: 0,0:13:05.62,0:13:08.82,Default,,0000,0000,0000,,the key part of Perspectives, is that we want Dialogue: 0,0:13:08.82,0:13:11.95,Default,,0000,0000,0000,,to be able to share our templates between\Nthe Dialogue: 0,0:13:11.95,0:13:13.92,Default,,0000,0000,0000,,client and the server. So like the server\Nshould Dialogue: 0,0:13:13.92,0:13:16.12,Default,,0000,0000,0000,,be able to render full HTML. And the client Dialogue: 0,0:13:16.12,0:13:17.66,Default,,0000,0000,0000,,should be able to like receive JSON and like Dialogue: 0,0:13:17.66,0:13:18.100,Default,,0000,0000,0000,,render a template, right. This is sort of\Nthe Dialogue: 0,0:13:18.100,0:13:21.10,Default,,0000,0000,0000,,appeal of something like render. Dialogue: 0,0:13:21.10,0:13:28.10,Default,,0000,0000,0000,,So, here, you know, let's, let's say we thought, Dialogue: 0,0:13:28.50,0:13:30.71,Default,,0000,0000,0000,,well maybe we can sort of share templates.\NMaybe Dialogue: 0,0:13:30.71,0:13:32.90,Default,,0000,0000,0000,,we can share our existing erb templates. Those\Nare Dialogue: 0,0:13:32.90,0:13:35.01,Default,,0000,0000,0000,,pretty easy to write. So here's like a simple Dialogue: 0,0:13:35.01,0:13:36.94,Default,,0000,0000,0000,,erb template, right. We're just generating\Nlike a link Dialogue: 0,0:13:36.94,0:13:38.65,Default,,0000,0000,0000,,to a user. We're using the name as like Dialogue: 0,0:13:38.65,0:13:41.87,Default,,0000,0000,0000,,the anchor text. We're using user_url helper\Nfrom Rails Dialogue: 0,0:13:41.87,0:13:43.79,Default,,0000,0000,0000,,to like generate a link to it. This is Dialogue: 0,0:13:43.79,0:13:47.40,Default,,0000,0000,0000,,pretty simple. You might imagine that using\Nsomething like Dialogue: 0,0:13:47.40,0:13:50.67,Default,,0000,0000,0000,,Opal, which transforms Ruby in JavaScript,\Nyou could like Dialogue: 0,0:13:50.67,0:13:53.39,Default,,0000,0000,0000,,pour it your whole server, kind of like, instance, Dialogue: 0,0:13:53.39,0:13:56.81,Default,,0000,0000,0000,,including all these helpers link link_to and\Nuser_url, to Dialogue: 0,0:13:56.81,0:13:58.91,Default,,0000,0000,0000,,JavaScript, and then you could just jump down\Nyour Dialogue: 0,0:13:58.91,0:14:01.03,Default,,0000,0000,0000,,erb template and then that could get sort\Nof Dialogue: 0,0:14:01.03,0:14:02.58,Default,,0000,0000,0000,,rendered on the client. Dialogue: 0,0:14:02.58,0:14:04.41,Default,,0000,0000,0000,,This might, you know, you might think that\Nthis Dialogue: 0,0:14:04.41,0:14:06.96,Default,,0000,0000,0000,,works. But, actually, you can kind of do more Dialogue: 0,0:14:06.96,0:14:09.31,Default,,0000,0000,0000,,stuff in erb than you might sort of be Dialogue: 0,0:14:09.31,0:14:11.73,Default,,0000,0000,0000,,aware of from simple examples. Like, you can,\Nhere's Dialogue: 0,0:14:11.73,0:14:13.72,Default,,0000,0000,0000,,an example, where I'm actually just running\Nlike a Dialogue: 0,0:14:13.72,0:14:16.53,Default,,0000,0000,0000,,SQL query in an erb template. And this, I Dialogue: 0,0:14:16.53,0:14:21.51,Default,,0000,0000,0000,,think, demonstrates like, the fundamental\Ndifference - yeah, boo! Dialogue: 0,0:14:21.51,0:14:24.78,Default,,0000,0000,0000,,This, I think, demonstrates like a fundamental\Ndifference between, Dialogue: 0,0:14:24.78,0:14:27.55,Default,,0000,0000,0000,,you know, the client and the server, is that, Dialogue: 0,0:14:27.55,0:14:30.42,Default,,0000,0000,0000,,they're kind of in different environments.\NLike, the server Dialogue: 0,0:14:30.42,0:14:33.15,Default,,0000,0000,0000,,has access to resources that the client, not\Nonly Dialogue: 0,0:14:33.15,0:14:35.33,Default,,0000,0000,0000,,doesn't have access to but shouldn't have\Naccess to. Dialogue: 0,0:14:35.33,0:14:37.61,Default,,0000,0000,0000,,The client should not ever be able to like Dialogue: 0,0:14:37.61,0:14:39.61,Default,,0000,0000,0000,,hook up to the database and ask some questions. Dialogue: 0,0:14:39.61,0:14:42.18,Default,,0000,0000,0000,,Right, so. And the client is the same. Like, Dialogue: 0,0:14:42.18,0:14:44.34,Default,,0000,0000,0000,,the client knows stuff about the user's browser.\NLike, Dialogue: 0,0:14:44.34,0:14:46.66,Default,,0000,0000,0000,,they can inspect local storage and all this\Nstuff. Dialogue: 0,0:14:46.66,0:14:49.74,Default,,0000,0000,0000,,Like, they're fundamentally different environments.\NAnd so I don't Dialogue: 0,0:14:49.74,0:14:52.28,Default,,0000,0000,0000,,think that any of the existing templates out\Nthere Dialogue: 0,0:14:52.28,0:14:54.63,Default,,0000,0000,0000,,really get you this sort of shared environment\Nfor Dialogue: 0,0:14:54.63,0:14:55.85,Default,,0000,0000,0000,,free. Dialogue: 0,0:14:55.85,0:14:59.85,Default,,0000,0000,0000,,So, the way, you know, so the way to Dialogue: 0,0:14:59.85,0:15:02.88,Default,,0000,0000,0000,,get to a shared template between a client\Nand Dialogue: 0,0:15:02.88,0:15:05.46,Default,,0000,0000,0000,,a server is to find the lowest common denominator. Dialogue: 0,0:15:05.46,0:15:08.26,Default,,0000,0000,0000,,So, like, if you've taken, you know, calculus\Nat Dialogue: 0,0:15:08.26,0:15:10.21,Default,,0000,0000,0000,,the graduate level, you might have heard of\Nthe Dialogue: 0,0:15:10.21,0:15:13.64,Default,,0000,0000,0000,,lowest common denominator. It's the way that\Nyou are Dialogue: 0,0:15:13.64,0:15:16.33,Default,,0000,0000,0000,,able to like, if you're trying to add fractions, Dialogue: 0,0:15:16.33,0:15:18.67,Default,,0000,0000,0000,,you can like, multiply the denominator- Dialogue: 0,0:15:18.67,0:15:20.85,Default,,0000,0000,0000,,The point is, it allows you to like find Dialogue: 0,0:15:20.85,0:15:24.52,Default,,0000,0000,0000,,some common ground between, you know, the\Nclient and Dialogue: 0,0:15:24.52,0:15:28.16,Default,,0000,0000,0000,,the server, right. So we need lowest common\Ndenominator. Dialogue: 0,0:15:28.16,0:15:30.39,Default,,0000,0000,0000,,Which is the dumbest possible template. So\Nwe need Dialogue: 0,0:15:30.39,0:15:32.94,Default,,0000,0000,0000,,something that's really dumb, that has, that\Nbasically can't Dialogue: 0,0:15:32.94,0:15:36.24,Default,,0000,0000,0000,,do anything. And so what is that? Well, that's Dialogue: 0,0:15:36.24,0:15:39.40,Default,,0000,0000,0000,,mustache. Mustache are the dumbest templates\Nout there. Don't Dialogue: 0,0:15:39.40,0:15:40.67,Default,,0000,0000,0000,,tell them I said that. They're probably in\Nthe Dialogue: 0,0:15:40.67,0:15:43.40,Default,,0000,0000,0000,,other room or something. But they're, they're\Npretty dumb. Dialogue: 0,0:15:43.40,0:15:46.98,Default,,0000,0000,0000,,You know, you might have heard mustache templates\Nreferred Dialogue: 0,0:15:46.98,0:15:49.92,Default,,0000,0000,0000,,to as being logic-less. I actually think logic-less\Nis Dialogue: 0,0:15:49.92,0:15:51.67,Default,,0000,0000,0000,,kind of like a bad way of describing it. Dialogue: 0,0:15:51.67,0:15:53.92,Default,,0000,0000,0000,,Because when I hear logic-less, I'm kind of\Nthinking, Dialogue: 0,0:15:53.92,0:15:55.90,Default,,0000,0000,0000,,like, OK, I can't write like an if statement. Dialogue: 0,0:15:55.90,0:15:58.85,Default,,0000,0000,0000,,There's probably no like for loop situation.\NLike, what Dialogue: 0,0:15:58.85,0:15:59.86,Default,,0000,0000,0000,,else can't I do? Well I probably can't do Dialogue: 0,0:15:59.86,0:16:02.33,Default,,0000,0000,0000,,like an if-else, like, you know, the reality\Nis Dialogue: 0,0:16:02.33,0:16:04.34,Default,,0000,0000,0000,,you can actually kind of do that stuff. It's Dialogue: 0,0:16:04.34,0:16:06.20,Default,,0000,0000,0000,,called a different thing. So I don't like\Nusing Dialogue: 0,0:16:06.20,0:16:07.51,Default,,0000,0000,0000,,the word logic-less. Dialogue: 0,0:16:07.51,0:16:09.61,Default,,0000,0000,0000,,It's more like you can't run arbitrary code.\NIt's Dialogue: 0,0:16:09.61,0:16:13.07,Default,,0000,0000,0000,,more like no code, code-less or something.\NSo you Dialogue: 0,0:16:13.07,0:16:15.04,Default,,0000,0000,0000,,can't run arbitrary code. This is the sort\Nof Dialogue: 0,0:16:15.04,0:16:18.05,Default,,0000,0000,0000,,take away from mustache, right. And so, you\Nknow, Dialogue: 0,0:16:18.05,0:16:20.20,Default,,0000,0000,0000,,this is kind of cool because, because you\Ncan't Dialogue: 0,0:16:20.20,0:16:23.53,Default,,0000,0000,0000,,run arbitrary code, we can write mustache\Ntemplate renders Dialogue: 0,0:16:23.53,0:16:26.35,Default,,0000,0000,0000,,in all these different languages. So you can\Neasily Dialogue: 0,0:16:26.35,0:16:29.83,Default,,0000,0000,0000,,render mustache templates in Ruby or JavaScript.\NIf you Dialogue: 0,0:16:29.83,0:16:31.49,Default,,0000,0000,0000,,want to use one of these other languages,\Nthese Dialogue: 0,0:16:31.49,0:16:33.33,Default,,0000,0000,0000,,are terrible, but I guess you could use like Dialogue: 0,0:16:33.33,0:16:35.07,Default,,0000,0000,0000,,dot net or something if you wanted to render Dialogue: 0,0:16:35.07,0:16:37.62,Default,,0000,0000,0000,,a mustache template in dot net. I don't know Dialogue: 0,0:16:37.62,0:16:38.62,Default,,0000,0000,0000,,what you're doing but you might be able to Dialogue: 0,0:16:38.62,0:16:40.01,Default,,0000,0000,0000,,do that. Dialogue: 0,0:16:40.01,0:16:42.49,Default,,0000,0000,0000,,So, to show you like how to create a Dialogue: 0,0:16:42.49,0:16:43.84,Default,,0000,0000,0000,,mustache template, I want to look at like\Na Dialogue: 0,0:16:43.84,0:16:46.87,Default,,0000,0000,0000,,specific example. So here's, like, the RailsGenius\Napp, and, Dialogue: 0,0:16:46.87,0:16:49.37,Default,,0000,0000,0000,,you know, in the left, lower left-hand corner\Nhere Dialogue: 0,0:16:49.37,0:16:52.16,Default,,0000,0000,0000,,there's like an annotation, right. So this\Nis sort Dialogue: 0,0:16:52.16,0:16:55.62,Default,,0000,0000,0000,,of annotating the line node.js. And if we\Nsort Dialogue: 0,0:16:55.62,0:16:57.45,Default,,0000,0000,0000,,of zoom in on this thing, we can see Dialogue: 0,0:16:57.45,0:16:59.66,Default,,0000,0000,0000,,there are a few different components. Dialogue: 0,0:16:59.66,0:17:02.55,Default,,0000,0000,0000,,There's the section of text that's annotated.\NSo we'll Dialogue: 0,0:17:02.55,0:17:04.55,Default,,0000,0000,0000,,call that the referent. This is like a fancy Dialogue: 0,0:17:04.55,0:17:07.31,Default,,0000,0000,0000,,word for like reference or something. So we'll\Ncall Dialogue: 0,0:17:07.31,0:17:09.66,Default,,0000,0000,0000,,that the referent. That's the line that I\Nhighlighted Dialogue: 0,0:17:09.66,0:17:12.16,Default,,0000,0000,0000,,and explained. And then we'll call this the\Nsort Dialogue: 0,0:17:12.16,0:17:15.06,Default,,0000,0000,0000,,of body. And you'll notice the body can contain Dialogue: 0,0:17:15.06,0:17:17.96,Default,,0000,0000,0000,,like arbitrary HTML. There's a link to node.js\Ndot Dialogue: 0,0:17:17.96,0:17:20.10,Default,,0000,0000,0000,,org. A link to Ruby on Rails, et cetera. Dialogue: 0,0:17:20.10,0:17:22.49,Default,,0000,0000,0000,,I'm sort of adding, like, you know, I'm adding Dialogue: 0,0:17:22.49,0:17:25.46,Default,,0000,0000,0000,,hyper media here because it's the web. Dialogue: 0,0:17:25.46,0:17:26.83,Default,,0000,0000,0000,,And then there's this edit link, right. And\Nso Dialogue: 0,0:17:26.83,0:17:28.86,Default,,0000,0000,0000,,this edit link, you might imagine, should\Nappear for Dialogue: 0,0:17:28.86,0:17:31.88,Default,,0000,0000,0000,,some users and not others depending on, like,\Nwhat Dialogue: 0,0:17:31.88,0:17:34.56,Default,,0000,0000,0000,,your permissions are or what your sort of\Nsituation Dialogue: 0,0:17:34.56,0:17:36.69,Default,,0000,0000,0000,,is. Dialogue: 0,0:17:36.69,0:17:39.66,Default,,0000,0000,0000,,And so mustache, the, the template for this,\Nthe Dialogue: 0,0:17:39.66,0:17:42.23,Default,,0000,0000,0000,,whole template, looks like this. So I'm gonna\Ngo Dialogue: 0,0:17:42.23,0:17:44.07,Default,,0000,0000,0000,,into like the specifics of how I would actually, Dialogue: 0,0:17:44.07,0:17:46.39,Default,,0000,0000,0000,,you know, what this is doing. But here's the Dialogue: 0,0:17:46.39,0:17:48.95,Default,,0000,0000,0000,,template. And to render this, I just need\Nthis Dialogue: 0,0:17:48.95,0:17:51.64,Default,,0000,0000,0000,,hash of JSON data. So I can render this Dialogue: 0,0:17:51.64,0:17:53.76,Default,,0000,0000,0000,,anywhere as long as I have this hash. Key Dialogue: 0,0:17:53.76,0:17:55.85,Default,,0000,0000,0000,,thing to remember. Dialogue: 0,0:17:55.85,0:18:00.60,Default,,0000,0000,0000,,So, if I can't run code in mustache, like Dialogue: 0,0:18:00.60,0:18:03.61,Default,,0000,0000,0000,,I can run code in erb, how do I Dialogue: 0,0:18:03.61,0:18:06.04,Default,,0000,0000,0000,,actually like put data in the markup, which\Nis Dialogue: 0,0:18:06.04,0:18:09.01,Default,,0000,0000,0000,,like the whole point of templates, right? Dialogue: 0,0:18:09.01,0:18:11.30,Default,,0000,0000,0000,,So you can use these tags. Right, so given Dialogue: 0,0:18:11.30,0:18:14.84,Default,,0000,0000,0000,,this section of JSON, you have a referent\Nmapping Dialogue: 0,0:18:14.84,0:18:18.14,Default,,0000,0000,0000,,to node dot js, right. We can render that Dialogue: 0,0:18:18.14,0:18:21.03,Default,,0000,0000,0000,,data into this template with a, you know,\Ninside Dialogue: 0,0:18:21.03,0:18:23.13,Default,,0000,0000,0000,,of a block quote, by using this double curly Dialogue: 0,0:18:23.13,0:18:26.23,Default,,0000,0000,0000,,brace thing. This just says, like, basically,\Ngsub, or Dialogue: 0,0:18:26.23,0:18:29.27,Default,,0000,0000,0000,,actually not gsub, sub this referant into,\Ninside this Dialogue: 0,0:18:29.27,0:18:30.71,Default,,0000,0000,0000,,block quote. Pretty simple. Dialogue: 0,0:18:30.71,0:18:32.27,Default,,0000,0000,0000,,So this is just gonna print like block quote Dialogue: 0,0:18:32.27,0:18:37.22,Default,,0000,0000,0000,,node.js, you know. That should hopefully be\Nfairly self-evident. Dialogue: 0,0:18:37.22,0:18:39.41,Default,,0000,0000,0000,,So if you want to sort of do something Dialogue: 0,0:18:39.41,0:18:41.85,Default,,0000,0000,0000,,where you're printing raw HTML, the double\Nbrace will Dialogue: 0,0:18:41.85,0:18:44.28,Default,,0000,0000,0000,,actually escape it. So that's most the time\Nwhat Dialogue: 0,0:18:44.28,0:18:46.39,Default,,0000,0000,0000,,you want. But in this case we're actually\Nlike, Dialogue: 0,0:18:46.39,0:18:49.61,Default,,0000,0000,0000,,you know, we want hyper media in that annotation. Dialogue: 0,0:18:49.61,0:18:51.83,Default,,0000,0000,0000,,So this, you know, actually has an href. An Dialogue: 0,0:18:51.83,0:18:52.69,Default,,0000,0000,0000,,a tag, rather. Dialogue: 0,0:18:52.69,0:18:55.44,Default,,0000,0000,0000,,So we're gonna use the triple brace, which\Nis Dialogue: 0,0:18:55.44,0:18:57.47,Default,,0000,0000,0000,,another type of tag that says print this HTML Dialogue: 0,0:18:57.47,0:19:00.15,Default,,0000,0000,0000,,raw. So this will actually print out, like,\Nyou Dialogue: 0,0:19:00.15,0:19:02.78,Default,,0000,0000,0000,,know, real anchor tag. Which is, in this case, Dialogue: 0,0:19:02.78,0:19:05.56,Default,,0000,0000,0000,,what we want. So here is the sort of Dialogue: 0,0:19:05.56,0:19:07.60,Default,,0000,0000,0000,,meat of mustache. This is probably the trickiest\Npart Dialogue: 0,0:19:07.60,0:19:10.40,Default,,0000,0000,0000,,of mustache. There's another type of tag which\Nis Dialogue: 0,0:19:10.40,0:19:13.99,Default,,0000,0000,0000,,this sort of double brace hash block, right. Dialogue: 0,0:19:13.99,0:19:16.96,Default,,0000,0000,0000,,So here is the block that I'm talking about. Dialogue: 0,0:19:16.96,0:19:18.33,Default,,0000,0000,0000,,So you can see this double brace, and then Dialogue: 0,0:19:18.33,0:19:20.82,Default,,0000,0000,0000,,there's hash edit. This hash is kind of where Dialogue: 0,0:19:20.82,0:19:23.08,Default,,0000,0000,0000,,the logic by another name comes into play\Nin Dialogue: 0,0:19:23.08,0:19:25.61,Default,,0000,0000,0000,,mustache. So this is going to, if edit is Dialogue: 0,0:19:25.61,0:19:27.88,Default,,0000,0000,0000,,like, a boolean type thing, it's going to\Nrun, Dialogue: 0,0:19:27.88,0:19:30.37,Default,,0000,0000,0000,,or, or go into the block. If edit is Dialogue: 0,0:19:30.37,0:19:33.64,Default,,0000,0000,0000,,true, if edit is like a list of something, Dialogue: 0,0:19:33.64,0:19:35.34,Default,,0000,0000,0000,,it basically is your for loop is the way Dialogue: 0,0:19:35.34,0:19:36.61,Default,,0000,0000,0000,,to think about it. Dialogue: 0,0:19:36.61,0:19:37.96,Default,,0000,0000,0000,,There's one more thing that is like if edit Dialogue: 0,0:19:37.96,0:19:40.19,Default,,0000,0000,0000,,is like a hash, it kind of just will Dialogue: 0,0:19:40.19,0:19:44.41,Default,,0000,0000,0000,,run the intersection if the hash is there.\NOtherwise Dialogue: 0,0:19:44.41,0:19:46.57,Default,,0000,0000,0000,,it won't. So in this case, we're just saying, Dialogue: 0,0:19:46.57,0:19:48.22,Default,,0000,0000,0000,,you know, we should show the edit link. That's Dialogue: 0,0:19:48.22,0:19:50.26,Default,,0000,0000,0000,,what edit true means. This is our logic by Dialogue: 0,0:19:50.26,0:19:54.11,Default,,0000,0000,0000,,another name. And then we're actually, you\Nknow, grabbing Dialogue: 0,0:19:54.11,0:19:57.34,Default,,0000,0000,0000,,the edit href from the JSON hash as well. Dialogue: 0,0:19:57.34,0:19:59.01,Default,,0000,0000,0000,,And so this will result in just putting the, Dialogue: 0,0:19:59.01,0:20:00.14,Default,,0000,0000,0000,,printing the edit link. Dialogue: 0,0:20:00.14,0:20:03.09,Default,,0000,0000,0000,,Now if edit were false, it wouldn't print\Nthat. Dialogue: 0,0:20:03.09,0:20:04.83,Default,,0000,0000,0000,,And so you might be asking, like, well what Dialogue: 0,0:20:04.83,0:20:06.33,Default,,0000,0000,0000,,if I wanted to do something else. Like I'm Dialogue: 0,0:20:06.33,0:20:09.86,Default,,0000,0000,0000,,used to writing these if-else statements.\NSo mustache also Dialogue: 0,0:20:09.86,0:20:12.97,Default,,0000,0000,0000,,has this other sort of tag, which is a Dialogue: 0,0:20:12.97,0:20:16.75,Default,,0000,0000,0000,,carrot. SO there's like double, double squiggly,\Ndouble curly Dialogue: 0,0:20:16.75,0:20:19.44,Default,,0000,0000,0000,,brace, carot edit, which just means sort of\Ngo Dialogue: 0,0:20:19.44,0:20:22.52,Default,,0000,0000,0000,,into this block if edit is unset or false. Dialogue: 0,0:20:22.52,0:20:25.02,Default,,0000,0000,0000,,So this is the kind of last tag. So Dialogue: 0,0:20:25.02,0:20:27.07,Default,,0000,0000,0000,,in this case, if edit were false, we would Dialogue: 0,0:20:27.07,0:20:29.97,Default,,0000,0000,0000,,just print can't edit. So this is mustache.\NThat's Dialogue: 0,0:20:29.97,0:20:32.07,Default,,0000,0000,0000,,basically all you can do. Dialogue: 0,0:20:32.07,0:20:34.78,Default,,0000,0000,0000,,So how does this actually help us? Well, I Dialogue: 0,0:20:34.78,0:20:36.72,Default,,0000,0000,0000,,don't know if you guys remember, but at the Dialogue: 0,0:20:36.72,0:20:40.23,Default,,0000,0000,0000,,beginning of this mustache section, I showed\Nyou this Dialogue: 0,0:20:40.23,0:20:42.52,Default,,0000,0000,0000,,template and I said all you need to render Dialogue: 0,0:20:42.52,0:20:44.98,Default,,0000,0000,0000,,this template is this hash. And I also told Dialogue: 0,0:20:44.98,0:20:47.09,Default,,0000,0000,0000,,you that there's a Ruby library for this and Dialogue: 0,0:20:47.09,0:20:48.78,Default,,0000,0000,0000,,a JavaScript library for this. Dialogue: 0,0:20:48.78,0:20:49.71,Default,,0000,0000,0000,,So I think you might see where this is Dialogue: 0,0:20:49.71,0:20:51.85,Default,,0000,0000,0000,,going. If we have some way of generating like Dialogue: 0,0:20:51.85,0:20:54.55,Default,,0000,0000,0000,,a hash, anywhere, then we can render it, we Dialogue: 0,0:20:54.55,0:20:57.07,Default,,0000,0000,0000,,can ship the template and the hash to any Dialogue: 0,0:20:57.07,0:21:00.11,Default,,0000,0000,0000,,environment and like render it there. Dialogue: 0,0:21:00.11,0:21:01.41,Default,,0000,0000,0000,,That's the point I'm trying to make. So how Dialogue: 0,0:21:01.41,0:21:03.81,Default,,0000,0000,0000,,do we actually generate this hash? That's\Nthe sort Dialogue: 0,0:21:03.81,0:21:05.64,Default,,0000,0000,0000,,of tricky part. Well I'm gonna do some handwaving Dialogue: 0,0:21:05.64,0:21:08.08,Default,,0000,0000,0000,,here and say, well, this, Perspective's library\Nmight help Dialogue: 0,0:21:08.08,0:21:10.29,Default,,0000,0000,0000,,us a little bit. Dialogue: 0,0:21:10.29,0:21:12.81,Default,,0000,0000,0000,,So you know here's a traditional Rails view.\NThis Dialogue: 0,0:21:12.81,0:21:15.79,Default,,0000,0000,0000,,is like an erb template, right. And so what Dialogue: 0,0:21:15.79,0:21:17.94,Default,,0000,0000,0000,,I'm saying is that if we split this into Dialogue: 0,0:21:17.94,0:21:21.61,Default,,0000,0000,0000,,a template, which is mustache, and a perspective,\Nwhich Dialogue: 0,0:21:21.61,0:21:25.01,Default,,0000,0000,0000,,is something, it's a new type of object, then Dialogue: 0,0:21:25.01,0:21:27.30,Default,,0000,0000,0000,,we can just have this data transport thing,\Nwhich Dialogue: 0,0:21:27.30,0:21:29.22,Default,,0000,0000,0000,,is just the hash, which is generated by the Dialogue: 0,0:21:29.22,0:21:32.49,Default,,0000,0000,0000,,perspective. And then we can render the template\Nanywhere. Dialogue: 0,0:21:32.49,0:21:33.75,Default,,0000,0000,0000,,So this is how we render on the client Dialogue: 0,0:21:33.75,0:21:35.61,Default,,0000,0000,0000,,or the server. Dialogue: 0,0:21:35.61,0:21:37.75,Default,,0000,0000,0000,,So what is this perspective thing look like?\NWell, Dialogue: 0,0:21:37.75,0:21:40.29,Default,,0000,0000,0000,,as you might imagine, it's a bunch of stuff Dialogue: 0,0:21:40.29,0:21:44.37,Default,,0000,0000,0000,,that specifies what is in the hash. So, here's Dialogue: 0,0:21:44.37,0:21:46.54,Default,,0000,0000,0000,,the whole perspective. I'm gonna dive into\Ndifferent parts Dialogue: 0,0:21:46.54,0:21:48.58,Default,,0000,0000,0000,,of it. But you can see it's just basically Dialogue: 0,0:21:48.58,0:21:50.71,Default,,0000,0000,0000,,a Ruby object with like some macros thrown\Nin. Dialogue: 0,0:21:50.71,0:21:52.47,Default,,0000,0000,0000,,That's, that's sort of the goal of the library. Dialogue: 0,0:21:52.47,0:21:55.51,Default,,0000,0000,0000,,It should just be a Ruby object. Plain Ruby Dialogue: 0,0:21:55.51,0:21:56.53,Default,,0000,0000,0000,,object. Dialogue: 0,0:21:56.53,0:21:59.84,Default,,0000,0000,0000,,So you can specify inputs, which you specify\Nwith Dialogue: 0,0:21:59.84,0:22:02.78,Default,,0000,0000,0000,,params. So you can say param annotation, this\Nperspective Dialogue: 0,0:22:02.78,0:22:07.87,Default,,0000,0000,0000,,expects an annotation as input. You can specify\Noutputs. Dialogue: 0,0:22:07.87,0:22:12.33,Default,,0000,0000,0000,,This perspective outputs reference, which\Nis the annotation's referent Dialogue: 0,0:22:12.33,0:22:16.28,Default,,0000,0000,0000,,property. It also specifies body as a key.\NAnd Dialogue: 0,0:22:16.28,0:22:18.51,Default,,0000,0000,0000,,that's the annotation's body as HTML. So this\Nis Dialogue: 0,0:22:18.51,0:22:20.03,Default,,0000,0000,0000,,gonna be raw HTML. Dialogue: 0,0:22:20.03,0:22:24.04,Default,,0000,0000,0000,,And so properties our output. And so these\Nare Dialogue: 0,0:22:24.04,0:22:26.80,Default,,0000,0000,0000,,actually just keys in this hash. So we can Dialogue: 0,0:22:26.80,0:22:30.93,Default,,0000,0000,0000,,just turn this perspective object into a JSON\Nobject Dialogue: 0,0:22:30.93,0:22:32.96,Default,,0000,0000,0000,,and then that can be rendered anywhere. So\Nnow Dialogue: 0,0:22:32.96,0:22:35.69,Default,,0000,0000,0000,,that we know what this perspective object\Nis, it Dialogue: 0,0:22:35.69,0:22:37.94,Default,,0000,0000,0000,,should be pretty self-explanatory how we get\Nfrom the Dialogue: 0,0:22:37.94,0:22:40.53,Default,,0000,0000,0000,,right over to the left and render this template. Dialogue: 0,0:22:40.53,0:22:42.59,Default,,0000,0000,0000,,Now you might be thinking, isn't this just\Nlike Dialogue: 0,0:22:42.59,0:22:45.65,Default,,0000,0000,0000,,a fancy version of like helpers or something?\NLike, Dialogue: 0,0:22:45.65,0:22:48.75,Default,,0000,0000,0000,,helpers with like a namespace? And it's actually\Ndifferent Dialogue: 0,0:22:48.75,0:22:52.14,Default,,0000,0000,0000,,because, you know, helpers are sort of operating\Nat, Dialogue: 0,0:22:52.14,0:22:54.13,Default,,0000,0000,0000,,they seem like they kind of live in their Dialogue: 0,0:22:54.13,0:22:57.38,Default,,0000,0000,0000,,own separate object, like annotations' helper\Nor something. But Dialogue: 0,0:22:57.38,0:22:59.91,Default,,0000,0000,0000,,actually they're in a global namespace which\Ncan be Dialogue: 0,0:22:59.91,0:23:02.03,Default,,0000,0000,0000,,called from any template at any time. And\Nso Dialogue: 0,0:23:02.03,0:23:04.16,Default,,0000,0000,0000,,they can kind of like override each other. Dialogue: 0,0:23:04.16,0:23:06.81,Default,,0000,0000,0000,,They also are direct function indication.\NSo this is Dialogue: 0,0:23:06.81,0:23:09.10,Default,,0000,0000,0000,,just data. This hash in the middle is just Dialogue: 0,0:23:09.10,0:23:12.07,Default,,0000,0000,0000,,data. SO like if you reference a property\Ntwice, Dialogue: 0,0:23:12.07,0:23:14.24,Default,,0000,0000,0000,,you're always gonna get the same value, unlike\Na Dialogue: 0,0:23:14.24,0:23:16.59,Default,,0000,0000,0000,,helper, which could theoretically return different\Nthings if you Dialogue: 0,0:23:16.59,0:23:18.62,Default,,0000,0000,0000,,call it different times. SO it's kind of like Dialogue: 0,0:23:18.62,0:23:22.46,Default,,0000,0000,0000,,a safer thing for us as developers. Dialogue: 0,0:23:22.46,0:23:25.43,Default,,0000,0000,0000,,And so to build like an app with this, Dialogue: 0,0:23:25.43,0:23:27.65,Default,,0000,0000,0000,,you can imagine the initial request that the\Nclient Dialogue: 0,0:23:27.65,0:23:30.88,Default,,0000,0000,0000,,makes will receive HTML so the, the server\Nwill Dialogue: 0,0:23:30.88,0:23:33.67,Default,,0000,0000,0000,,say, OK let me take this perspective thing,\Nturn Dialogue: 0,0:23:33.67,0:23:35.92,Default,,0000,0000,0000,,it into JSON, render in mustache template\Nand then Dialogue: 0,0:23:35.92,0:23:37.87,Default,,0000,0000,0000,,send that back to the user. And, in the Dialogue: 0,0:23:37.87,0:23:39.66,Default,,0000,0000,0000,,case of like new Twitter, the user would just Dialogue: 0,0:23:39.66,0:23:42.18,Default,,0000,0000,0000,,see the 140 character Tweet rendered. And\Nin the Dialogue: 0,0:23:42.18,0:23:45.24,Default,,0000,0000,0000,,case of like a web-crawler for a search engine, Dialogue: 0,0:23:45.24,0:23:46.51,Default,,0000,0000,0000,,it would see like the full HTML that it Dialogue: 0,0:23:46.51,0:23:47.80,Default,,0000,0000,0000,,can then index. Dialogue: 0,0:23:47.80,0:23:50.02,Default,,0000,0000,0000,,And then subsequent requests, just like we\Nwould do Dialogue: 0,0:23:50.02,0:23:52.33,Default,,0000,0000,0000,,with like Ember or Backbone or whatever, we\Njust Dialogue: 0,0:23:52.33,0:23:54.57,Default,,0000,0000,0000,,request JSON from the server and then we render Dialogue: 0,0:23:54.57,0:23:58.52,Default,,0000,0000,0000,,the part of the page that needs to change. Dialogue: 0,0:23:58.52,0:24:02.08,Default,,0000,0000,0000,,So, you the know, the key thing here I Dialogue: 0,0:24:02.08,0:24:05.66,Default,,0000,0000,0000,,think is that HTML is unstructured data. And\Nso Dialogue: 0,0:24:05.66,0:24:08.05,Default,,0000,0000,0000,,a lot of like sort of Rails patterns will Dialogue: 0,0:24:08.05,0:24:10.62,Default,,0000,0000,0000,,tell you just return like the snippet of HTML Dialogue: 0,0:24:10.62,0:24:12.89,Default,,0000,0000,0000,,from the server that you need and then snap Dialogue: 0,0:24:12.89,0:24:15.81,Default,,0000,0000,0000,,that in somewhere. And the eventually leads\Nto like Dialogue: 0,0:24:15.81,0:24:20.09,Default,,0000,0000,0000,,soupy code and coupling to like classes on\NHTML Dialogue: 0,0:24:20.09,0:24:21.93,Default,,0000,0000,0000,,elements, which leads to a lot of like weirdo Dialogue: 0,0:24:21.93,0:24:24.05,Default,,0000,0000,0000,,bugs that are hard to track down. Dialogue: 0,0:24:24.05,0:24:26.83,Default,,0000,0000,0000,,JSON, on the other hand, is structured data.\NIt's Dialogue: 0,0:24:26.83,0:24:29.28,Default,,0000,0000,0000,,a lot easier to deal with this, so, you Dialogue: 0,0:24:29.28,0:24:31.35,Default,,0000,0000,0000,,can either render it or you could do something, Dialogue: 0,0:24:31.35,0:24:33.81,Default,,0000,0000,0000,,you know, on the client that's a little fancier. Dialogue: 0,0:24:33.81,0:24:35.36,Default,,0000,0000,0000,,If you want to do, update different parts\Nof Dialogue: 0,0:24:35.36,0:24:37.65,Default,,0000,0000,0000,,the page, whatever. The point is that it's\Nstructured Dialogue: 0,0:24:37.65,0:24:39.47,Default,,0000,0000,0000,,and it's easy to deal with. And if you're Dialogue: 0,0:24:39.47,0:24:43.12,Default,,0000,0000,0000,,building out like a thick client, you want\Nto Dialogue: 0,0:24:43.12,0:24:47.77,Default,,0000,0000,0000,,couple your client experience to structured\Ndata, not unstructured Dialogue: 0,0:24:47.77,0:24:48.66,Default,,0000,0000,0000,,data. Dialogue: 0,0:24:48.66,0:24:51.78,Default,,0000,0000,0000,,All right, so I'm gonna do the quick getting Dialogue: 0,0:24:51.78,0:24:53.30,Default,,0000,0000,0000,,started. You know this is, this is sort of Dialogue: 0,0:24:53.30,0:24:54.83,Default,,0000,0000,0000,,about this library, but I don't want it to Dialogue: 0,0:24:54.83,0:24:56.49,Default,,0000,0000,0000,,be all about this library. So, you know, it's Dialogue: 0,0:24:56.49,0:24:58.81,Default,,0000,0000,0000,,just a gem. You can just generate the install Dialogue: 0,0:24:58.81,0:25:01.93,Default,,0000,0000,0000,,for it. That'll like make your app perspectivified.\NYou Dialogue: 0,0:25:01.93,0:25:05.22,Default,,0000,0000,0000,,can scaffold stuff. You know, you break your\Nerb Dialogue: 0,0:25:05.22,0:25:10.31,Default,,0000,0000,0000,,templates into mustache templates and a perspective.\NAnd you Dialogue: 0,0:25:10.31,0:25:13.26,Default,,0000,0000,0000,,just add this one line to your controller,\Nso Dialogue: 0,0:25:13.26,0:25:15.03,Default,,0000,0000,0000,,this just uses a responder to figure out if Dialogue: 0,0:25:15.03,0:25:18.12,Default,,0000,0000,0000,,the client wants HTML or wants JSON, and turns Dialogue: 0,0:25:18.12,0:25:19.84,Default,,0000,0000,0000,,the perspective into whatever you want to.\NIn this Dialogue: 0,0:25:19.84,0:25:22.71,Default,,0000,0000,0000,,case, it's just, you know, find this annotation\Nby Dialogue: 0,0:25:22.71,0:25:26.09,Default,,0000,0000,0000,,ID. Use this little macro to create your perspective Dialogue: 0,0:25:26.09,0:25:27.77,Default,,0000,0000,0000,,and pass it the data it needs, which in Dialogue: 0,0:25:27.77,0:25:29.66,Default,,0000,0000,0000,,this case is like an annotation. And then\Nwe Dialogue: 0,0:25:29.66,0:25:33.65,Default,,0000,0000,0000,,can render a JSON version or an HTML version. Dialogue: 0,0:25:33.65,0:25:37.71,Default,,0000,0000,0000,,So what else does this buy us? So clearly Dialogue: 0,0:25:37.71,0:25:39.64,Default,,0000,0000,0000,,this rendering on the client and server thing\Nis Dialogue: 0,0:25:39.64,0:25:43.32,Default,,0000,0000,0000,,pretty good. But actually, I didn't like set\Nout, Dialogue: 0,0:25:43.32,0:25:45.12,Default,,0000,0000,0000,,when I was thinking about this, to like build Dialogue: 0,0:25:45.12,0:25:47.40,Default,,0000,0000,0000,,some sort of like new thick client like framework Dialogue: 0,0:25:47.40,0:25:49.60,Default,,0000,0000,0000,,thing that competes with Ember. That wasn't\Nmy goal Dialogue: 0,0:25:49.60,0:25:52.88,Default,,0000,0000,0000,,and I'm still not sure that's my goal. The Dialogue: 0,0:25:52.88,0:25:54.51,Default,,0000,0000,0000,,benefits I'm about to tell you about were\Nactually Dialogue: 0,0:25:54.51,0:25:57.14,Default,,0000,0000,0000,,like the initial inspiration for like wanting\Nto build Dialogue: 0,0:25:57.14,0:25:58.14,Default,,0000,0000,0000,,this library. Dialogue: 0,0:25:58.14,0:26:02.91,Default,,0000,0000,0000,,So, number one is separation of concerns.\NSo, I Dialogue: 0,0:26:02.91,0:26:06.86,Default,,0000,0000,0000,,really hate seeing erb templates like this.\NHere's like Dialogue: 0,0:26:06.86,0:26:08.65,Default,,0000,0000,0000,,an erb version of the template I just showed Dialogue: 0,0:26:08.65,0:26:10.68,Default,,0000,0000,0000,,you. So instead of having like a nice edit Dialogue: 0,0:26:10.68,0:26:14.20,Default,,0000,0000,0000,,property, there's often like some logic in\Nhere, if Dialogue: 0,0:26:14.20,0:26:17.39,Default,,0000,0000,0000,,you look at the bottom there, that's checking,\Nlike, Dialogue: 0,0:26:17.39,0:26:18.97,Default,,0000,0000,0000,,whether or not to show the edit link. And Dialogue: 0,0:26:18.97,0:26:20.73,Default,,0000,0000,0000,,this is kind of ugly. It's kind of ugly Dialogue: 0,0:26:20.73,0:26:23.24,Default,,0000,0000,0000,,no matter where it lives. But it's especially\Nugly Dialogue: 0,0:26:23.24,0:26:24.52,Default,,0000,0000,0000,,if it lives in a template. Dialogue: 0,0:26:24.52,0:26:26.06,Default,,0000,0000,0000,,And it is so easy to do this with Dialogue: 0,0:26:26.06,0:26:29.12,Default,,0000,0000,0000,,erb, cause, you know, erb literally just means\Nembedded Dialogue: 0,0:26:29.12,0:26:31.51,Default,,0000,0000,0000,,Ruby. So you can just write anything. Like\NI, Dialogue: 0,0:26:31.51,0:26:33.61,Default,,0000,0000,0000,,like I've seen saying. SO like here we're\Nsaying, Dialogue: 0,0:26:33.61,0:26:36.51,Default,,0000,0000,0000,,the person can edit the annotation if they\Ncreated Dialogue: 0,0:26:36.51,0:26:39.38,Default,,0000,0000,0000,,or they're like a super admin type, type,\Ntype Dialogue: 0,0:26:39.38,0:26:41.93,Default,,0000,0000,0000,,user. Dialogue: 0,0:26:41.93,0:26:47.42,Default,,0000,0000,0000,,So, mustache and perspectives force you into\Nthis separation Dialogue: 0,0:26:47.42,0:26:49.85,Default,,0000,0000,0000,,of concerns, where you literally can't write\Nany code Dialogue: 0,0:26:49.85,0:26:51.79,Default,,0000,0000,0000,,in your template. So you have to put it Dialogue: 0,0:26:51.79,0:26:54.11,Default,,0000,0000,0000,,in the perspective, which is just a Ruby object, Dialogue: 0,0:26:54.11,0:26:56.09,Default,,0000,0000,0000,,which is where it kind of belongs. And there's Dialogue: 0,0:26:56.09,0:26:59.60,Default,,0000,0000,0000,,no, there's no love for this in erb land Dialogue: 0,0:26:59.60,0:27:01.49,Default,,0000,0000,0000,,in Rails. You're kind of, you're kind of off Dialogue: 0,0:27:01.49,0:27:03.37,Default,,0000,0000,0000,,in this waste land of like, I guess I'll Dialogue: 0,0:27:03.37,0:27:05.36,Default,,0000,0000,0000,,throw some view logic in here. I don't really Dialogue: 0,0:27:05.36,0:27:07.58,Default,,0000,0000,0000,,know where it's supposed to go. Dialogue: 0,0:27:07.58,0:27:08.97,Default,,0000,0000,0000,,And so this, this leads me to like, so Dialogue: 0,0:27:08.97,0:27:11.44,Default,,0000,0000,0000,,here's the, sorry, here's the perspective\Nversion of it, Dialogue: 0,0:27:11.44,0:27:14.03,Default,,0000,0000,0000,,where actually just generate this edit property\Nand say Dialogue: 0,0:27:14.03,0:27:15.89,Default,,0000,0000,0000,,whether or not we want to display the link, Dialogue: 0,0:27:15.89,0:27:19.46,Default,,0000,0000,0000,,based on that logic I showed you before. Dialogue: 0,0:27:19.46,0:27:20.80,Default,,0000,0000,0000,,So this also gives you like, testing. So I Dialogue: 0,0:27:20.80,0:27:22.83,Default,,0000,0000,0000,,now DHH was like, you know, shitting on this Dialogue: 0,0:27:22.83,0:27:26.23,Default,,0000,0000,0000,,in his talk. I still think testing is important. Dialogue: 0,0:27:26.23,0:27:28.18,Default,,0000,0000,0000,,Maybe not TDD. But like the point is, if Dialogue: 0,0:27:28.18,0:27:30.72,Default,,0000,0000,0000,,you wanted to test like an erb template and Dialogue: 0,0:27:30.72,0:27:33.20,Default,,0000,0000,0000,,had some logic in this, in it, you would Dialogue: 0,0:27:33.20,0:27:34.82,Default,,0000,0000,0000,,have to like, render, the only thing you can Dialogue: 0,0:27:34.82,0:27:36.73,Default,,0000,0000,0000,,do is render the template. You can't talk\Nto Dialogue: 0,0:27:36.73,0:27:38.20,Default,,0000,0000,0000,,it. It's not an object. You can't ask it Dialogue: 0,0:27:38.20,0:27:40.32,Default,,0000,0000,0000,,questions. All you can do is render it and Dialogue: 0,0:27:40.32,0:27:41.99,Default,,0000,0000,0000,,then do like a string-match on it. Dialogue: 0,0:27:41.99,0:27:43.17,Default,,0000,0000,0000,,And in fact, I've seen a ton of tests Dialogue: 0,0:27:43.17,0:27:45.93,Default,,0000,0000,0000,,like this. Web driver tests are basically\Njust doing Dialogue: 0,0:27:45.93,0:27:48.32,Default,,0000,0000,0000,,like, advanced regexes to like figure out\Nif the Dialogue: 0,0:27:48.32,0:27:51.49,Default,,0000,0000,0000,,logic is right. And this is really bad. A Dialogue: 0,0:27:51.49,0:27:53.87,Default,,0000,0000,0000,,perspective is just a freakin' object. Like\Nyou just Dialogue: 0,0:27:53.87,0:27:55.69,Default,,0000,0000,0000,,new it up and pass it the data it Dialogue: 0,0:27:55.69,0:27:57.78,Default,,0000,0000,0000,,needs and then you can test your logic. SO Dialogue: 0,0:27:57.78,0:28:00.01,Default,,0000,0000,0000,,here I'm just creating a test double. You\Nknow, Dialogue: 0,0:28:00.01,0:28:02.45,Default,,0000,0000,0000,,test doubles are important in testing. Test\Ndouble for Dialogue: 0,0:28:02.45,0:28:04.95,Default,,0000,0000,0000,,a user, test double for an annotation. I'm\Ncreating Dialogue: 0,0:28:04.95,0:28:07.90,Default,,0000,0000,0000,,this new perspective and then I'm asking it\Nif Dialogue: 0,0:28:07.90,0:28:10.40,Default,,0000,0000,0000,,the edit link is true and verifying that it Dialogue: 0,0:28:10.40,0:28:13.66,Default,,0000,0000,0000,,should be showing that. Dialogue: 0,0:28:13.66,0:28:16.66,Default,,0000,0000,0000,,So another thing is caching. So this is like Dialogue: 0,0:28:16.66,0:28:19.40,Default,,0000,0000,0000,,maybe a little bit difficult to motivate,\Nbut like, Dialogue: 0,0:28:19.40,0:28:22.40,Default,,0000,0000,0000,,this sort of like cache digest thing, Russian\Ndoll Dialogue: 0,0:28:22.40,0:28:23.79,Default,,0000,0000,0000,,caching thing is kind of hard for me to Dialogue: 0,0:28:23.79,0:28:25.95,Default,,0000,0000,0000,,like wrap my brain around, right. Like, you\Nhave Dialogue: 0,0:28:25.95,0:28:27.85,Default,,0000,0000,0000,,to, you have to write, sometimes, like a special Dialogue: 0,0:28:27.85,0:28:30.43,Default,,0000,0000,0000,,comment to get the templates to know about\Neach Dialogue: 0,0:28:30.43,0:28:33.84,Default,,0000,0000,0000,,other. Not as good as just having objects\Nthat Dialogue: 0,0:28:33.84,0:28:34.79,Default,,0000,0000,0000,,know about each other. Dialogue: 0,0:28:34.79,0:28:38.22,Default,,0000,0000,0000,,So if you want to cache an annotation show Dialogue: 0,0:28:38.22,0:28:40.45,Default,,0000,0000,0000,,perspective, you just use this cache macro\Nand that Dialogue: 0,0:28:40.45,0:28:44.43,Default,,0000,0000,0000,,says, use the annotation as the cache key,\Nright. Dialogue: 0,0:28:44.43,0:28:46.44,Default,,0000,0000,0000,,And so if you're familiar with, like, cache\Nkeys Dialogue: 0,0:28:46.44,0:28:48.89,Default,,0000,0000,0000,,in Rails, if you're using generational caching,\Nthis will Dialogue: 0,0:28:48.89,0:28:50.33,Default,,0000,0000,0000,,just say, the cache key - hopefully you can Dialogue: 0,0:28:50.33,0:28:52.60,Default,,0000,0000,0000,,see this - is just the type of object, Dialogue: 0,0:28:52.60,0:28:54.28,Default,,0000,0000,0000,,the id of the object, and when it was Dialogue: 0,0:28:54.28,0:28:55.14,Default,,0000,0000,0000,,last updated. Dialogue: 0,0:28:55.14,0:28:56.60,Default,,0000,0000,0000,,So this will like fall out of cache if Dialogue: 0,0:28:56.60,0:28:58.100,Default,,0000,0000,0000,,anyone updates the annotation or if it's like\Na Dialogue: 0,0:28:58.100,0:29:00.98,Default,,0000,0000,0000,,different annotation it'll have a different\Ncache key. So Dialogue: 0,0:29:00.98,0:29:05.10,Default,,0000,0000,0000,,this sort of, hopefully this is, is somewhat\Nfamiliar. Dialogue: 0,0:29:05.10,0:29:07.24,Default,,0000,0000,0000,,If you have another template that you're rendering,\Nlike Dialogue: 0,0:29:07.24,0:29:11.41,Default,,0000,0000,0000,,here, this annotation show perspective, is\Nrendering a nested Dialogue: 0,0:29:11.41,0:29:13.69,Default,,0000,0000,0000,,user slash avatar perspective, so you can\Nsee that Dialogue: 0,0:29:13.69,0:29:16.34,Default,,0000,0000,0000,,at the bottom. You might want to say, well, Dialogue: 0,0:29:16.34,0:29:18.64,Default,,0000,0000,0000,,if the user updates their avatar, we also\Nwant Dialogue: 0,0:29:18.64,0:29:19.70,Default,,0000,0000,0000,,this to fall out of cache. Dialogue: 0,0:29:19.70,0:29:22.17,Default,,0000,0000,0000,,This is sort of the, the Russian doll caching Dialogue: 0,0:29:22.17,0:29:24.63,Default,,0000,0000,0000,,of it all, right. So if the inside Russian Dialogue: 0,0:29:24.63,0:29:26.96,Default,,0000,0000,0000,,doll is uncached then it should bust the outside Dialogue: 0,0:29:26.96,0:29:30.18,Default,,0000,0000,0000,,Russian dolls cache key. So this thing, you\Ncan Dialogue: 0,0:29:30.18,0:29:32.64,Default,,0000,0000,0000,,also assign a cache key to. You can say, Dialogue: 0,0:29:32.64,0:29:34.38,Default,,0000,0000,0000,,cache based on the user. So if the user Dialogue: 0,0:29:34.38,0:29:37.38,Default,,0000,0000,0000,,gets updated from the user's avatar perspective,\Nwe want Dialogue: 0,0:29:37.38,0:29:39.96,Default,,0000,0000,0000,,this to fall out of cache. And so, like Dialogue: 0,0:29:39.96,0:29:41.55,Default,,0000,0000,0000,,I said, we want the whole thing to fall Dialogue: 0,0:29:41.55,0:29:43.66,Default,,0000,0000,0000,,out of cache if the user gets updated or Dialogue: 0,0:29:43.66,0:29:45.68,Default,,0000,0000,0000,,the annotation gets updated. Dialogue: 0,0:29:45.68,0:29:47.69,Default,,0000,0000,0000,,And so what perspective will do for you is Dialogue: 0,0:29:47.69,0:29:50.12,Default,,0000,0000,0000,,say, OK, we know that there's a nested user's Dialogue: 0,0:29:50.12,0:29:52.84,Default,,0000,0000,0000,,avatar perspective here, and so to generate\Nthe cache Dialogue: 0,0:29:52.84,0:29:54.89,Default,,0000,0000,0000,,key for this whole thing, we're just going\Nto Dialogue: 0,0:29:54.89,0:29:57.93,Default,,0000,0000,0000,,concatenate the cache key from the annotation\Nand the Dialogue: 0,0:29:57.93,0:30:00.27,Default,,0000,0000,0000,,cache key from the user and produce this ugly, Dialogue: 0,0:30:00.27,0:30:02.09,Default,,0000,0000,0000,,terrible, long cache key, which you don't\Nhave to Dialogue: 0,0:30:02.09,0:30:04.64,Default,,0000,0000,0000,,worry about at any point as the writer of Dialogue: 0,0:30:04.64,0:30:05.65,Default,,0000,0000,0000,,the code. Dialogue: 0,0:30:05.65,0:30:07.76,Default,,0000,0000,0000,,So this is all sort of handled transparently\Nfor Dialogue: 0,0:30:07.76,0:30:12.25,Default,,0000,0000,0000,,you. So are we ready to sail off, to Dialogue: 0,0:30:12.25,0:30:14.98,Default,,0000,0000,0000,,drive off into the sunset in Rails land now Dialogue: 0,0:30:14.98,0:30:18.88,Default,,0000,0000,0000,,with this new stuff? Well, not quite. The,\Nthe Dialogue: 0,0:30:18.88,0:30:21.50,Default,,0000,0000,0000,,point I'm trying to make here is that, or Dialogue: 0,0:30:21.50,0:30:22.53,Default,,0000,0000,0000,,one thing I want to get across here is Dialogue: 0,0:30:22.53,0:30:24.25,Default,,0000,0000,0000,,that this is sort of a nascent library slash Dialogue: 0,0:30:24.25,0:30:28.08,Default,,0000,0000,0000,,weekend project motivated by, you know, having,\Nmaking it Dialogue: 0,0:30:28.08,0:30:31.88,Default,,0000,0000,0000,,annoying to like, do caching, and it's hard\Nto Dialogue: 0,0:30:31.88,0:30:35.10,Default,,0000,0000,0000,,kind of separate your, your templates out,\Nand also Dialogue: 0,0:30:35.10,0:30:36.60,Default,,0000,0000,0000,,I'd like to be able to like render the Dialogue: 0,0:30:36.60,0:30:39.66,Default,,0000,0000,0000,,same thing on the client and server. But there's Dialogue: 0,0:30:39.66,0:30:41.10,Default,,0000,0000,0000,,still a bunch of stuff to be done, right. Dialogue: 0,0:30:41.10,0:30:42.84,Default,,0000,0000,0000,,Like there's still some work to be done to Dialogue: 0,0:30:42.84,0:30:45.59,Default,,0000,0000,0000,,like integrate this with existing like frontend\Nframeworks if Dialogue: 0,0:30:45.59,0:30:48.42,Default,,0000,0000,0000,,you want to add like a bunch more rich Dialogue: 0,0:30:48.42,0:30:50.70,Default,,0000,0000,0000,,experiences on the client. Dialogue: 0,0:30:50.70,0:30:53.60,Default,,0000,0000,0000,,And I want to get to the point, though, Dialogue: 0,0:30:53.60,0:30:55.55,Default,,0000,0000,0000,,where we can have a good answer to these Dialogue: 0,0:30:55.55,0:30:57.41,Default,,0000,0000,0000,,node.js libraries. Like this is a big motivation.\NLike Dialogue: 0,0:30:57.41,0:31:00.11,Default,,0000,0000,0000,,I'm tired of node.js being, like, well let's\Njust Dialogue: 0,0:31:00.11,0:31:04.78,Default,,0000,0000,0000,,embrace JavaScript. Like, no let's not embrace\NJavaScript. Ruby. Dialogue: 0,0:31:04.78,0:31:08.06,Default,,0000,0000,0000,,Ruby is better. So let's, let's get at them. Dialogue: 0,0:31:08.06,0:31:10.01,Default,,0000,0000,0000,,But, the key take away is you shouldn't be Dialogue: 0,0:31:10.01,0:31:12.50,Default,,0000,0000,0000,,sort of creating one version of your app that Dialogue: 0,0:31:12.50,0:31:14.11,Default,,0000,0000,0000,,lives on the server and one that lives on Dialogue: 0,0:31:14.11,0:31:17.30,Default,,0000,0000,0000,,the client. The ideal situation is move most\Nof Dialogue: 0,0:31:17.30,0:31:19.41,Default,,0000,0000,0000,,the stuff to the server but be able to Dialogue: 0,0:31:19.41,0:31:23.11,Default,,0000,0000,0000,,like still create this thick client situation. Dialogue: 0,0:31:23.11,0:31:25.44,Default,,0000,0000,0000,,So that's it. That's my talk. You can check Dialogue: 0,0:31:25.44,0:31:28.97,Default,,0000,0000,0000,,out this library by going to RapGenius slash\Nperspectives Dialogue: 0,0:31:28.97,0:31:31.14,Default,,0000,0000,0000,,on GitHub, or if you're lazy, there's this\Nbit.ly Dialogue: 0,0:31:31.14,0:31:34.04,Default,,0000,0000,0000,,link. bit.ly slash RG perspectives. And also,\Nas I Dialogue: 0,0:31:34.04,0:31:36.66,Default,,0000,0000,0000,,said at the beginning of the talk, we are Dialogue: 0,0:31:36.66,0:31:38.98,Default,,0000,0000,0000,,hiring. So if you're sort of interested in\Nthis Dialogue: 0,0:31:38.98,0:31:41.81,Default,,0000,0000,0000,,kind of stuff or other stuff Rap Genius related, Dialogue: 0,0:31:41.81,0:31:43.15,Default,,0000,0000,0000,,get at me. Hit me up on Twitter. Hit Dialogue: 0,0:31:43.15,0:31:45.88,Default,,0000,0000,0000,,me up via email. Andy at RapGenius dot com. Dialogue: 0,0:31:45.88,0:31:48.20,Default,,0000,0000,0000,,And I think we have time for some questions.