Your Front End Framework is Overkill - Server Side Javascript w/ Rails
CC Attribution - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Jones, Jim
For dynamic apps, Rails has taken a backseat to client side frameworks such as AngularJS, Ember and Backbone. Learn how to use server side javascript effectively to greatly simplify your code base and reuse your view logic. We'll implement parallel apps with vanilla Rails js responses, AngularJS and Ember.js so that we can contrast the implementations and evaluate the tradeoffs.
 Thanks for coming to my talk, you guys. I really appreciate it. My name is Jim Jones. I work as a Rails engineer consultant. I'm currently at One Kings Lane and I've lived in San Francisco for the past five years. I just recently moved back to Nebraska because my wife and I had a baby. I love everything, this karaoke and beer and I love being a dad and I really love the city of San Francisco. On a slightly side story, one of the first experiences I had when I moved to San Francisco was I went to the Taco Bell and I struck up a conversation. This is the Outer Mission Excelsior, one of the few Taco Bells in the city. I struck up a conversation with the cashier and she started complaining about the rendering differences between her Windows phone and the Android phone. I'm pretty sure she said the word render and I thought to myself, I go, holy shit, I'm in another place right here. I had a secondary experience where we went to Wells Fargo and we were opening a joint account for my wife and I got married. The banker asked me, hey, what do you do for a living? I said, yeah, I'm a software engineer. His eyes light up and he said, what language? I said, Ruby. He said, oh my God, I wrote a few scripts to automate some of the balances I need to know at the end of the day. He was like the second where the fuck am I at? I really missed those sorts of interactions and such. It was a whole new world and it was where I got to meet lots of the people that I had really well respected over the years and such. Great experience. When I got there, I went to a company called Z-Benz and we eventually got acquired by StubHub. After that, I ended up striking out on my own doing consulting. I just had this whirlwind of experience as I went to San Francisco that I got to tell my grandchildren about and going through an acquisition and being out on my own and learning on my own. That's just a little bit of a background about me. Today we're here to talk about dynamic sites and dynamic sites with Rails. We have a few options here. We have just raw JavaScript which is actually becoming a little bit more in favor now that people, now that implementations are starting to match up with the modern browsers and such, it's probably not as far fetched as a lot of people seem to believe. We have jQuery which obviously is going to take care of a lot of the browser idiosyncrasies and differences and such. That's always the go-to on a lot of projects. We start to get these higher structure layer of abstractions. We have Backbone that's going to give us a little more structure to our front end. We have Ember.js that we're getting even further with all of its nice conventions and such. Then we have the directives with Angular that are really, really powerful and then give us even more structure to our app. Then there's this little stepchild that no one ever really talks about and not even sure most people are really aware of what the capabilities are in the current Rails stack. The point is that everything has its place and that the front end framework certainly have their advantages. Then we also have the server side JavaScript rendering which is going to, we're going to show where its advantages are and where it shines. We're going to go through a few parallel implementations here of the exact same app. I'm going to attempt to do some live coding and commit presentation suicide. We'll go from there. First off, we have to qualify this. For anybody who's been with Rails for a long time, I'm not talking about RJS. I think a lot of people still call it RJS. This is probably maybe a problem with the evangelism of this particular subset. If you guys remember, it depends on how far back you go with Rails and the history, but there's functionality called Ruby JavaScript. You probably remember very explicit method naming conventions like this where you had link to remote and here's this really cool URL hash where we're explicitly telling our controller and action and such. We have our page.replace HTML. We would get these JavaScript requests and then we would get this page object and we were able to either replace a particular HTML element or we were able to update an HTML element. I think that this was the Rails way of trying to solve for the sweet spots of what the dynamic sites were doing back then, which were just basic updating and such. But at the end of the day, it was very constraining and it ended up getting ripped out of Rails core. In fact, I was trying to figure out when the transitions went from just RJS responses to raw JavaScript responses. I was looking at my agile books and I think the agile two still was citing RJS. I assume around it was Rails three that we started to see just the standard JavaScript suicide requests. But someone else can crack me. We started to kind of take the kid gloves off of our JavaScript requests and I think it's around Rails three that we start to allow for free form JavaScript responses. I think this is going to be better demonstrated with some code. Let's see what we can do here. I have this application. This is just a standard, Rails new. Is everybody okay on that? Can everyone see? We just have a user model. We just have a name on it. I've already done the DB migrate on it, but that's about it. That's all we're at at this point. And so what I would like to do is currently we have this functionality. It's listing of users. We have a new user. We want to add a user and we would like it to dynamically update. Okay. So the out of the box is like, all right. So we've got that. This is just a plain scaffolding coming right out of the box. So now how can we get this where it's a dynamic where we would just start adding users to our table and without pulling in any sort of external JavaScript frameworks? So we'll go back to our source and I'll kind of walk you through on how we're going to go ahead and massage this code, right? And so this is where you guys get to laugh at me because live coding never goes right, right? So let's see if we can create some magic here. Let's just do that. Yeah, let's just take the table and I'm going to go ahead and render out all the users and so that's just going to iterate over our user collection and it's going to call the user partial on that. So we're going to go ahead and we'll create our user partial. For those that have actually seen this in action, you'll probably be pretty bored but I think this bears repeating that I've consulted at a lot of companies and it might be people who tend to be newer to the Rails community tend to reach for their front end framework right away. They say, oh, Ajax, dynamic updates. Hey, we need to pull in a front end framework for this. And so the whole point of going through this exercise is that you can see this built up and you can see that there's a lot that comes in the box for Rails and a lot of your simple dynamic updates may already be taken care of and you may not have to add any more dependencies. So I just want to drive home that point by going through this. So let's just say, we'll just take that. So now we've got our sweet partial. Let's go here. Let's make sure it's still rendering. Nice. All right. So now we've got our partial setup. Okay. Now we're going to allow for a name to be entered right directly from the index. So we'll come over here. Let's get rid of that. Let's just say render. And we already have our nice little form extracted out because Rails is good to us for that. So let's make sure that that's rendering. And oh, so it needs a user object. We'll come over to our user controller. So here we're just going to say user.new. All right. So now we've got our form. Awesome. Great. So what if we enter a name here? Let's say, sir. Okay. We're still doing an HTTP request. Okay. Great. So now how we alter this is we'll go over here. We'll look at our form. And we'll just say remote true. And we're going to get into the magic behind this flag a little bit later. And we'll actually look at the implementation behind it. But just know from going forward that this is what enables the asynchronous submission of forms. All right. So we've got that. Let's go ahead and refresh. Tim. All right. Nothing. So we don't have anything. So let's see. Let's see what's going on the back end here. All right. We can see we've posted to users. And it was hitting users controller create as a JS. So now we've switched from standard HTTP posts to a JS request. Okay. So that's a good sign. That means we're at least posting up our data to the server. And if we were actually to hit a refresh on this, we would see that Tim was posted. Right? So now how do we get that data and we get it back to rendering? We come over here. We're going to go ahead and remember how we applied that ID of users to the T body. We're going to go ahead and do a little jQuery magic because that's included out of the box. We'll just say users. And we'll say.append. And here's the nice thing. Is that this particular template is going to be called create.js.erb. And so that implies that erb is doing a pass on this template before it serves up the raw JavaScript. So this is just another action template. And so that empowers us to go ahead and render out all of our partials, render out the very views that we've already built. And so we're going to get a lot of reusability out of this. So you're going to find that for a lot of simple dynamic updates, you're going to be a lot more productive with this. So we just want to do an escape, JavaScript, and we'll render user because we already have our user partial, right? And that was the one that constituted a row in our table. And we're missing the parentheses. No, sweet. So we'll just say users append. We're going to render out. So now we'll call this create.js.erb. So that's implying it's a JS request and it's going to be processed by the erb. All right. Now let's say I'll care. Try this. Let me say, oh, no, nothing happened. So maybe there's something wrong with my JavaScript. Let's take a look where it fell down. Let's see. Okay. Use the control, create, it's JS, commit. And then soon it's trying to use the controller. So we forgot one thing here. We're going to use this controller. On the create. We want to make sure that it's going to render the default JS template. So we're going to go ahead and pop in the format.js here. Now let's try this again. Boom. So now if we take a look at the life cycle of this, we have, we posted to users, we processed users controller create as JS. And then you can see right here that it rendered users create.js.erb. Send it client side and the default behavior for jQuery is to go ahead and evaluate a JavaScript request. And we'll dig more into the internals of that in a little bit. But just think of it as really, it's going to be really beneficial for you to see the full implementation of that, even though it was a little crude. So, all right. So just to reiterate, this is not RJS. This is way more free-formed. This is just raw JavaScript with erb processing. And that raw JavaScript is just getting sent client side. So it's getting that template will get processed by your template processor. It could be handle, it could be erb. And since this is ActionView, we get the full reuse of partials. We get all of our normal helpers. We get all of that included. It's just another type of template. All right. So I mentioned that we're going to look at some parallel implementations. What I have set up is we're going to take a look at the, there's a, there's a site called to do MVC that has a to do list implemented in various front end frameworks. You have like EmberJS. You have the AngularJS implementations. There's also a plain old Rails JavaScript response implementation as well. So I want to walk through some of the specifics of that code so that you can start to get a feel for a real world application. Do slides for top. All right. Let's just take a look here at our never request. All right. So if we take, say, do slides for top. All right. We'll take a look at this response. And this is just going back to the raw JavaScript response for the create method. You can see that the response is basically just to send back raw JavaScript. Right? And so we've got our to do list here. We're pending our list item. You can see the escape JavaScript method has properly escaped all of our quotes. We're just re-initializing our entry for the to do back to blank. And we're setting a few properties. And so that's it. If we take a look at the form, the form code for that, we just have a form for, we're just initializing a new to do. And we're just setting the remote true flag on it, similar to that initial implementation that we walk through. Here's our model. Pretty trivial model. Just have a couple of different scopes for completed and active. And we have our view. One thing to note here is J is basically an alias for escape JavaScript. So that can lead to a little bit of shortened code within your JS templates. But the most relevant portion is just this to do list. We're just pending. We're rendering out our to do. And then we're just going to go ahead and re-initialize our value. And we would just see this create.js right within our views for that particular resource. Here's our controller. Now I want to walk through what some of these helpers expand to. And so you have a little bit more background so that when things start going wrong, you aren't drawing a blank space and saying, why did this guy recommend this as an alternative and start cursing my name. If we were to look at that form for help or call and see it expanded, we would see that the action is set to to do. And the most important portion is that remote true ends up being extended to a data remote equals true. And we're going to see here in a little bit that this is something that JQuery UJS is actually looking for in order to do the asynchronous submissions. Right here, if you start digging through the JQuery UJS, JQuery UJS is the portion that is actually in charge of doing the asynchronous submission under the Rails JS. We're going to do document delegate for the form submit selector and digging through that method. If that remote flag is ended up true, we're just going to go ahead and do a Rails.handle remote. Further down, and we'll look at these events later on, but you're going to see on the handle remote implementation, you'll see a bunch of different firing of events, and there's going to be a series of events that you can actually listen to that are quite beneficial in terms of like for disabling controls, re-enabling controls, doing proper error display and so on. Here's our controller action. You could see the to use controller create. It was as a JS request. That's the important part. And it's important to note that we rendered out just using a standard partial. We escaped it. And this is also available if you're using Hamel as well. You can just do a regular string and it provides an interpolation right there. So you can still do the escape JavaScript render and still do that same output under Hamel. Here's the final portion. When it requests, it makes a JS request and it comes back. There's going to be a global eval on that particular request. And that actually becomes important when we start going over how to debug these things because evals aren't pretty when the code is incorrect. And so I'll give you a few tips on the debugging coming up after we go over these other implementations here. So it's important we're going to kind of just gloss over these front end implementations really quick, but it's important to kind of note some of the differences here. So call my what? That wolf. You wouldn't appreciate that. All right. If we start looking, breaking down the views on this Angular implementation, some of the, obviously some of the more important parts is like the to do app and then we have on our ng submit the other directive for an add to do. We come over here, we look at our controller and this is taken directly from the to do mvc implementation. We just have our add to do or saving. I have a couple of promises here and it persists that out depending on what store you have, whether it's api or local storage. Here's a services that provides that insert function for the store and they're just posting to the api to do. It's important to note that this is obviously you have full control over that. So that actually becomes important when we're discussing the advantages of the client side frameworks. Let's just sleep. That's definitely on the to do list sometime. Not now. That would be boring. We've got with our implementation, we've got our inline handlebars and inline handlebars template to script. So those are eval and with JavaScript client side. That's important. We have our controller. We're off just creating the record and saving it. And we just have a very simple model to represent this. So our client side advantages, we have immediate rendering, right, where because these templates are implemented in JavaScript, we can immediately render it to the screen regardless of whether what the result is. We could take that chance if we wanted to. And so that's certainly an advantage where it's hard to compare that even to like a 50 millisecond response time server side that you certainly get that immediacy with that if that's how you go ahead and design it. You can do asynchronous persistence. Also on the speed side where you can just go ahead and delegate that persistence out and you can still display things in the meantime and you'll get that immediacy, that quick update to the user interface that will delight the users. And then there's also like graceful error retries, right, since you are controlling this persistence loop that you can also do some nice graceful retrying if we lost internet connectivity or lost one of the servers and such and this could be totally transparent to the end user. So you have that level of granularity with the client side and you have that level of control. All right. So there's a few gotchas for the JavaScript server side responses that I think once you're aware of, it'll make it a little bit more pleasurable experience as you kind of do a deep dive into them. Debugging is definitely a big time gotcha. And I'm going to go ahead and just jump over here so you guys can see this firsthand. So like I said, when the JavaScript response gets sent back, it actually is going to eval that. And the big problem is any val fails silently. So if you happen to have a problem with your JavaScript and you just have this little typo in there, we go ahead and we're going to say try this three. We say create user. Oh, no, it just fails. And there's nothing. There's no guidance or there's no server side response because obviously we're just evaluating the template at that point. Server side, client side just eval it, just throw it hands up, didn't do anything. So that's definitely one of the frustrating components that new users basically have to figure out how to get around. And there's a couple of different ways that you can attack that. This is kind of a primer for where I'm going for the debugging. But we talked about all the different UJS callbacks and how they're triggered throughout the life cycle of the asynchronous request. And here's just a large table of the different states from within that asynchronous request that are available to you. And these probably don't get utilized enough or people aren't aware of them. But the one that we are concerned about is the AJAX error. And this will actually get thrown. This will get called when there's an eval error. And this is really helpful. You can drop this, say, like in your application JS or somewhere else. But if there is an error with the eval, we can at least go ahead and do a console log and output what that error text is so that you're not totally in the dark. I remember there's the old RJS, excuse me, the old RJS would actually wrap the code in a try catch block. And so I'll show something else along those lines. Excuse me. Sorry. I actually have a pull request out for Rails 5 that does just that where it will take the code, wrap it in a try catch block, and sends a series of metadata for where the error occurs with it or... Oh, my gosh. Excuse me. Sorry. I have a pull request out that tracks where JavaScript is generated, whether it's within a partial or within a template, sends that particular metadata over for the JavaScript request, wraps the execution in a try catch block, and then depending upon where the error is at, it'll say, hey, you have a JavaScript error, and it actually occurred in the user.html.erb partial or the user.js.erb template. And so it's trying to do some mapping back to where this JavaScript was actually produced. And it'll give a little more insight into the context in which this JavaScript was generated on the server side, but display it in a context in which people are used to debugging on the client side. So it's slated for 5.0. I don't know if it'll make it in, but it's been tagged. One big gotcha is if you are starting to do some replacements of HTML elements on your JavaScript responses, you're going to have to go ahead and re-bind those events. If you had, like, click handlers or something on certain div elements, you went ahead and replaced those, that particular handler is going to be lost. So you have to re-bind those. One way you can certainly do that is you could start to trigger callbacks, like on our cart summary. Okay, we can just trigger an updated app, and then within that updated app, we could just go ahead and re-bind those very events that we had set up in first. Some of the advantages for JS responses, obviously, since we're in ActionView, we get re-use of partials. So you can see in these two different examples, we've got our create.js.erb, where our user is not a pen, and we're rendering out our user partial. And then within that, for that same resource on our update, if we're doing an asynchronous dynamic update, we can just do user with the user ID, and we're just going to replace with, and we're going to render out this user, which would call the exact same partial. So you get all the advantages of ActionView right there within your JS templates. Along with that, you're going to have access to all your different view helpers, right? So that's going to include caching. So you could cache the hell out of these JS responses and get really lightning quick responses. And potentially, less JS load, right? That we're just sending over the pieces that need to be executed at that particular time. So it's certainly could constitute no reduction of JS, depending upon what you're doing. And there's also slight, depending upon who you ask, an easier execution flow that, because these are templates, they fall in line with the way the rest of the flow of how a Rails app generally goes. And so you would know, okay, I've got a JS request, I'm just going to look for this particular corresponding template. And it just will follow all the same sorts of conventions. So there's no deviation from that sort of mental model that's going to be used. All right. Finally, when do they make sense? I think they tend to make sense when it's something, when it's an interaction where the user expects some sort of level of persistence, something that's stored, something that, like a comment, or you've added a cart item, and you want to update cart count, you want to update, say, taxes or totals in another column, something where the user is expecting some level of persistence. I think this is where they can really shine, and they can certainly help to simplify a code base, just for the fact that you get so much reusability on there. And so I would just leave you with this final note. This was an article published not too long ago on Medium from Dan McKinley. He was a principal engineer at Etsy, and he just says, consider how you would solve your immediate problem without adding anything new. And so when you start to look at the dynamic updates, when you start to look at the pieces that you want to do, when you want to make dynamic, really, really give it a second thought as to whether you would want to adopt a full fledged framework, and that sort of overhead, or whether the JS responses would be sufficient in updating the individual pieces on the page. Thanks, you guys. I really appreciate it.
 Thanks for coming to my talk, you guys. I really appreciate it. My name is Jim Jones.  I work as a Rails engineer consultant. I'm currently at One Kings Lane and I've lived  in San Francisco for the past five years. I just recently moved back to Nebraska because  my wife and I had a baby. I love everything, this karaoke and beer and I love being a dad  and I really love the city of San Francisco. On a slightly side story, one of the first  experiences I had when I moved to San Francisco was I went to the Taco Bell and I struck up  a conversation. This is the Outer Mission Excelsior, one of the few Taco Bells in the  city. I struck up a conversation with the cashier and she started complaining about the rendering  differences between her Windows phone and the Android phone. I'm pretty sure she said  the word render and I thought to myself, I go, holy shit, I'm in another place right  here. I had a secondary experience where we went to Wells Fargo and we were opening a  joint account for my wife and I got married. The banker asked me, hey, what do you do for  a living? I said, yeah, I'm a software engineer. His eyes light up and he said, what language?  I said, Ruby. He said, oh my God, I wrote a few scripts to automate some of the balances  I need to know at the end of the day. He was like the second where the fuck am I at? I  really missed those sorts of interactions and such. It was a whole new world and it  was where I got to meet lots of the people that I had really well respected over the  years and such. Great experience. When I got there, I went to a company called Z-Benz  and we eventually got acquired by StubHub. After that, I ended up striking out on my  own doing consulting. I just had this whirlwind of experience as I went to San Francisco that  I got to tell my grandchildren about and going through an acquisition and being out on my  own and learning on my own. That's just a little bit of a background about me.  Today we're here to talk about dynamic sites and dynamic sites with Rails. We have a few  options here. We have just raw JavaScript which is actually becoming a little bit more  in favor now that people, now that implementations are starting to match up with the modern browsers  and such, it's probably not as far fetched as a lot of people seem to believe. We have  jQuery which obviously is going to take care of a lot of the browser idiosyncrasies and  differences and such. That's always the go-to on a lot of projects. We start to get these  higher structure layer of abstractions. We have Backbone that's going to give us a little  more structure to our front end. We have Ember.js that we're getting even further with all  of its nice conventions and such. Then we have the directives with Angular that are really,  really powerful and then give us even more structure to our app. Then there's this little  stepchild that no one ever really talks about and not even sure most people are really aware  of what the capabilities are in the current Rails stack.  The point is that everything has its place and that the front end framework certainly  have their advantages. Then we also have the server side JavaScript rendering which is  going to, we're going to show where its advantages are and where it shines. We're going to go  through a few parallel implementations here of the exact same app. I'm going to attempt  to do some live coding and commit presentation suicide. We'll go from there. First off, we  have to qualify this. For anybody who's been with Rails for a long time, I'm not talking  about RJS. I think a lot of people still call it RJS. This is probably maybe a problem with  the evangelism of this particular subset. If you guys remember, it depends on how far  back you go with Rails and the history, but there's functionality called Ruby JavaScript.  You probably remember very explicit method naming conventions like this where you had  link to remote and here's this really cool URL hash where we're explicitly telling our  controller and action and such. We have our page.replace HTML. We would get these JavaScript  requests and then we would get this page object and we were able to either replace a particular  HTML element or we were able to update an HTML element. I think that this was the Rails  way of trying to solve for the sweet spots of what the dynamic sites were doing back  then, which were just basic updating and such. But at the end of the day, it was very constraining  and it ended up getting ripped out of Rails core. In fact, I was trying to figure out  when the transitions went from just RJS responses to raw JavaScript responses. I was looking  at my agile books and I think the agile two still was citing RJS. I assume around it was  Rails three that we started to see just the standard JavaScript suicide requests. But  someone else can crack me. We started to kind of take the kid gloves off of our JavaScript  requests and I think it's around Rails three that we start to allow for free form JavaScript  responses. I think this is going to be better demonstrated with some code. Let's see what  we can do here. I have this application. This is just a standard, Rails new. Is everybody  okay on that? Can everyone see? We just have a user model. We just have a name on it. I've  already done the DB migrate on it, but that's about it. That's all we're at at this point.  And so what I would like to do is currently we have this functionality. It's listing  of users. We have a new user. We want to add a user and we would like it to dynamically  update. Okay. So the out of the box is like, all right. So we've got that. This is just  a plain scaffolding coming right out of the box. So now how can we get this where it's  a dynamic where we would just start adding users to our table and without pulling in  any sort of external JavaScript frameworks? So we'll go back to our source and I'll kind  of walk you through on how we're going to go ahead and massage this code, right? And  so this is where you guys get to laugh at me because live coding never goes right, right?  So let's see if we can create some magic here. Let's just do that. Yeah, let's just take  the table and I'm going to go ahead and render out all the users and so that's just going  to iterate over our user collection and it's going to call the user partial on that. So  we're going to go ahead and we'll create our user partial. For those that have actually  seen this in action, you'll probably be pretty bored but I think this bears repeating that  I've consulted at a lot of companies and it might be people who tend to be newer to the  Rails community tend to reach for their front end framework right away. They say, oh, Ajax,  dynamic updates. Hey, we need to pull in a front end framework for this. And so the whole  point of going through this exercise is that you can see this built up and you can see  that there's a lot that comes in the box for Rails and a lot of your simple dynamic updates  may already be taken care of and you may not have to add any more dependencies. So I just  want to drive home that point by going through this. So let's just say, we'll just take that.  So now we've got our sweet partial. Let's go here. Let's make sure it's still rendering.  Nice. All right. So now we've got our partial setup. Okay. Now we're going to allow for  a name to be entered right directly from the index. So we'll come over here. Let's get  rid of that. Let's just say render. And we already have our nice little form extracted  out because Rails is good to us for that. So let's make sure that that's rendering. And  oh, so it needs a user object. We'll come over to our user controller. So here we're  just going to say user.new. All right. So now we've got our form. Awesome. Great. So  what if we enter a name here? Let's say, sir. Okay. We're still doing an HTTP request.  Okay. Great. So now how we alter this is we'll go over here. We'll look at our form. And  we'll just say remote true. And we're going to get into the magic behind this flag a little  bit later. And we'll actually look at the implementation behind it. But just know from  going forward that this is what enables the asynchronous submission of forms. All right.  So we've got that. Let's go ahead and refresh. Tim. All right. Nothing. So we don't have anything.  So let's see. Let's see what's going on the back end here. All right. We can see we've  posted to users. And it was hitting users controller create as a JS. So now we've switched  from standard HTTP posts to a JS request. Okay. So that's a good sign. That means we're  at least posting up our data to the server. And if we were actually to hit a refresh on  this, we would see that Tim was posted. Right? So now how do we get that data and we get  it back to rendering? We come over here. We're going to go ahead and remember how we applied  that ID of users to the T body. We're going to go ahead and do a little jQuery magic  because that's included out of the box. We'll just say users. And we'll say.append. And  here's the nice thing. Is that this particular template is going to be called create.js.erb.  And so that implies that erb is doing a pass on this template before it serves up the raw  JavaScript. So this is just another action template. And so that empowers us to go ahead  and render out all of our partials, render out the very views that we've already built.  And so we're going to get a lot of reusability out of this. So you're going to find that  for a lot of simple dynamic updates, you're going to be a lot more productive with this.  So we just want to do an escape, JavaScript, and we'll render user because we already have  our user partial, right? And that was the one that constituted a row in our table. And  we're missing the parentheses. No, sweet. So we'll just say users append. We're going  to render out. So now we'll call this create.js.erb. So that's implying it's a JS request and it's  going to be processed by the erb. All right. Now let's say I'll care. Try this. Let me  say, oh, no, nothing happened. So maybe there's something wrong with my JavaScript. Let's  take a look where it fell down. Let's see. Okay. Use the control, create, it's JS, commit.  And then soon it's trying to use the controller. So we forgot one thing here. We're going to  use this controller. On the create. We want to make sure that it's going to render the  default JS template. So we're going to go ahead and pop in the format.js here. Now let's  try this again. Boom. So now if we take a look at the life cycle of this, we have, we  posted to users, we processed users controller create as JS. And then you can see right here  that it rendered users create.js.erb. Send it client side and the default behavior for  jQuery is to go ahead and evaluate a JavaScript request. And we'll dig more into the internals  of that in a little bit. But just think of it as really, it's going to be really beneficial  for you to see the full implementation of that, even though it was a little crude. So,  all right. So just to reiterate, this is not RJS. This is way more free-formed. This is  just raw JavaScript with erb processing. And that raw JavaScript is just getting sent  client side. So it's getting that template will get processed by your template processor.  It could be handle, it could be erb. And since this is ActionView, we get the full reuse  of partials. We get all of our normal helpers. We get all of that included. It's just another  type of template. All right. So I mentioned that we're going to look at some parallel  implementations. What I have set up is we're going to take a look at the, there's a, there's  a site called to do MVC that has a to do list implemented in various front end frameworks.  You have like EmberJS. You have the AngularJS implementations. There's also a plain old  Rails JavaScript response implementation as well. So I want to walk through some of the  specifics of that code so that you can start to get a feel for a real world application.  Do slides for top. All right. Let's just take a look here at our never request. All  right. So if we take, say, do slides for top. All right. We'll take a look at this response.  And this is just going back to the raw JavaScript response for the create method. You can see  that the response is basically just to send back raw JavaScript. Right? And so we've got  our to do list here. We're pending our list item. You can see the escape JavaScript method  has properly escaped all of our quotes. We're just re-initializing our entry for the to  do back to blank. And we're setting a few properties. And so that's it. If we take a look at the  form, the form code for that, we just have a form for, we're just initializing a new  to do. And we're just setting the remote true flag on it, similar to that initial implementation  that we walk through. Here's our model. Pretty trivial model. Just have a couple of different  scopes for completed and active. And we have our view. One thing to note here is J is basically  an alias for escape JavaScript. So that can lead to a little bit of shortened code within  your JS templates. But the most relevant portion is just this to do list. We're just  pending. We're rendering out our to do. And then we're just going to go ahead and re-initialize  our value. And we would just see this create.js right within our views for that particular  resource. Here's our controller. Now I want to walk through what some of these helpers  expand to. And so you have a little bit more background so that when things start going  wrong, you aren't drawing a blank space and saying, why did this guy recommend this as  an alternative and start cursing my name. If we were to look at that form for help or  call and see it expanded, we would see that the action is set to to do. And the most important  portion is that remote true ends up being extended to a data remote equals true. And  we're going to see here in a little bit that this is something that JQuery UJS is actually  looking for in order to do the asynchronous submissions. Right here, if you start digging  through the JQuery UJS, JQuery UJS is the portion that is actually in charge of doing  the asynchronous submission under the Rails JS. We're going to do document delegate for  the form submit selector and digging through that method. If that remote flag is ended up  true, we're just going to go ahead and do a Rails.handle remote. Further down, and we'll  look at these events later on, but you're going to see on the handle remote implementation,  you'll see a bunch of different firing of events, and there's going to be a series of  events that you can actually listen to that are quite beneficial in terms of like for  disabling controls, re-enabling controls, doing proper error display and so on. Here's  our controller action. You could see the to use controller create. It was as a JS request.  That's the important part. And it's important to note that we rendered out just using a  standard partial. We escaped it. And this is also available if you're using Hamel as  well. You can just do a regular string and it provides an interpolation right there.  So you can still do the escape JavaScript render and still do that same output under  Hamel. Here's the final portion. When it requests, it makes a JS request and it comes back. There's  going to be a global eval on that particular request. And that actually becomes important  when we start going over how to debug these things because evals aren't pretty when the  code is incorrect. And so I'll give you a few tips on the debugging coming up after we go  over these other implementations here. So it's important we're going to kind of just  gloss over these front end implementations really quick, but it's important to kind of  note some of the differences here. So call my what? That wolf. You wouldn't appreciate  that. All right. If we start looking, breaking down the views on this Angular implementation,  some of the, obviously some of the more important parts is like the to do app and then we have  on our ng submit the other directive for an add to do. We come over here, we look at our  controller and this is taken directly from the to do mvc implementation. We just have  our add to do or saving. I have a couple of promises here and it persists that out depending  on what store you have, whether it's api or local storage. Here's a services that provides  that insert function for the store and they're just posting to the api to do. It's important  to note that this is obviously you have full control over that. So that actually becomes  important when we're discussing the advantages of the client side frameworks. Let's just  sleep. That's definitely on the to do list sometime. Not now. That would be boring. We've  got with our implementation, we've got our inline handlebars and inline handlebars template  to script. So those are eval and with JavaScript client side. That's important. We have our  controller. We're off just creating the record and saving it. And we just have a very simple  model to represent this. So our client side advantages, we have immediate rendering, right,  where because these templates are implemented in JavaScript, we can immediately render it  to the screen regardless of whether what the result is. We could take that chance if we  wanted to. And so that's certainly an advantage where it's hard to compare that even to like  a 50 millisecond response time server side that you certainly get that immediacy with  that if that's how you go ahead and design it. You can do asynchronous persistence. Also  on the speed side where you can just go ahead and delegate that persistence out and you  can still display things in the meantime and you'll get that immediacy, that quick update  to the user interface that will delight the users. And then there's also like graceful  error retries, right, since you are controlling this persistence loop that you can also do  some nice graceful retrying if we lost internet connectivity or lost one of the servers and  such and this could be totally transparent to the end user. So you have that level of  granularity with the client side and you have that level of control. All right. So there's  a few gotchas for the JavaScript server side responses that I think once you're aware of,  it'll make it a little bit more pleasurable experience as you kind of do a deep dive into  them. Debugging is definitely a big time gotcha. And I'm going to go ahead and just jump over  here so you guys can see this firsthand. So like I said, when the JavaScript response  gets sent back, it actually is going to eval that. And the big problem is any val fails  silently. So if you happen to have a problem with your JavaScript and you just have this  little typo in there, we go ahead and we're going to say try this three. We say create  user. Oh, no, it just fails. And there's nothing. There's no guidance or there's no server side  response because obviously we're just evaluating the template at that point. Server side, client  side just eval it, just throw it hands up, didn't do anything. So that's definitely one  of the frustrating components that new users basically have to figure out how to get around.  And there's a couple of different ways that you can attack that. This is kind of a primer  for where I'm going for the debugging. But we talked about all the different UJS callbacks  and how they're triggered throughout the life cycle of the asynchronous request. And here's  just a large table of the different states from within that asynchronous request that  are available to you. And these probably don't get utilized enough or people aren't aware  of them. But the one that we are concerned about is the AJAX error. And this will actually  get thrown. This will get called when there's an eval error. And this is really helpful.  You can drop this, say, like in your application JS or somewhere else. But if there is an error  with the eval, we can at least go ahead and do a console log and output what that error  text is so that you're not totally in the dark. I remember there's the old RJS, excuse  me, the old RJS would actually wrap the code in a try catch block. And so I'll show something  else along those lines. Excuse me. Sorry. I actually have a pull request out for Rails  5 that does just that where it will take the code, wrap it in a try catch block, and sends  a series of metadata for where the error occurs with it or... Oh, my gosh. Excuse me. Sorry.  I have a pull request out that tracks where JavaScript is generated, whether it's within  a partial or within a template, sends that particular metadata over for the JavaScript  request, wraps the execution in a try catch block, and then depending upon where the error  is at, it'll say, hey, you have a JavaScript error, and it actually occurred in the user.html.erb  partial or the user.js.erb template. And so it's trying to do some mapping back to where  this JavaScript was actually produced. And it'll give a little more insight into the  context in which this JavaScript was generated on the server side, but display it in a context  in which people are used to debugging on the client side. So it's slated for 5.0. I don't  know if it'll make it in, but it's been tagged. One big gotcha is if you are starting to do  some replacements of HTML elements on your JavaScript responses, you're going to have  to go ahead and re-bind those events. If you had, like, click handlers or something on  certain div elements, you went ahead and replaced those, that particular handler is going to  be lost. So you have to re-bind those. One way you can certainly do that is you could  start to trigger callbacks, like on our cart summary. Okay, we can just trigger an updated  app, and then within that updated app, we could just go ahead and re-bind those very events  that we had set up in first. Some of the advantages for JS responses, obviously, since we're in  ActionView, we get re-use of partials. So you can see in these two different examples,  we've got our create.js.erb, where our user is not a pen, and we're rendering out our  user partial. And then within that, for that same resource on our update, if we're doing  an asynchronous dynamic update, we can just do user with the user ID, and we're just going  to replace with, and we're going to render out this user, which would call the exact  same partial. So you get all the advantages of ActionView right there within your JS  templates. Along with that, you're going to have access to all your different view helpers,  right? So that's going to include caching. So you could cache the hell out of these JS  responses and get really lightning quick responses. And potentially, less JS load, right? That  we're just sending over the pieces that need to be executed at that particular time. So  it's certainly could constitute no reduction of JS, depending upon what you're doing. And  there's also slight, depending upon who you ask, an easier execution flow that, because  these are templates, they fall in line with the way the rest of the flow of how a Rails  app generally goes. And so you would know, okay, I've got a JS request, I'm just going  to look for this particular corresponding template. And it just will follow all the  same sorts of conventions. So there's no deviation from that sort of mental model that's going  to be used. All right. Finally, when do they make sense? I think they tend to make sense  when it's something, when it's an interaction where the user expects some sort of level  of persistence, something that's stored, something that, like a comment, or you've added a cart  item, and you want to update cart count, you want to update, say, taxes or totals in another  column, something where the user is expecting some level of persistence. I think this is  where they can really shine, and they can certainly help to simplify a code base, just  for the fact that you get so much reusability on there. And so I would just leave you with  this final note. This was an article published not too long ago on Medium from Dan McKinley.  He was a principal engineer at Etsy, and he just says, consider how you would solve your  immediate problem without adding anything new. And so when you start to look at the dynamic  updates, when you start to look at the pieces that you want to do, when you want to make  dynamic, really, really give it a second thought as to whether you would want to adopt a full  fledged framework, and that sort of overhead, or whether the JS responses would be sufficient  in updating the individual pieces on the page. Thanks, you guys. I really appreciate it.
Your_Front_End_Framework_is_Overkill_0_47.png Your_Front_End_Framework_is_Overkill_48_155.png Your_Front_End_Framework_is_Overkill_156_299.png Your_Front_End_Framework_is_Overkill_300_10187.png Your_Front_End_Framework_is_Overkill_10188_10283.png Your_Front_End_Framework_is_Overkill_10284_10463.png Your_Front_End_Framework_is_Overkill_10464_11135.png Your_Front_End_Framework_is_Overkill_11136_11207.png Your_Front_End_Framework_is_Overkill_11208_12035.png Your_Front_End_Framework_is_Overkill_12036_14855.png Your_Front_End_Framework_is_Overkill_14856_15035.png Your_Front_End_Framework_is_Overkill_15036_15179.png Your_Front_End_Framework_is_Overkill_15180_15299.png Your_Front_End_Framework_is_Overkill_15300_15503.png Your_Front_End_Framework_is_Overkill_15504_15551.png Your_Front_End_Framework_is_Overkill_15552_15947.png Your_Front_End_Framework_is_Overkill_15948_16031.png Your_Front_End_Framework_is_Overkill_16032_16259.png Your_Front_End_Framework_is_Overkill_16260_16583.png Your_Front_End_Framework_is_Overkill_16584_17243.png Your_Front_End_Framework_is_Overkill_17244_17579.png Your_Front_End_Framework_is_Overkill_17580_18287.png Your_Front_End_Framework_is_Overkill_18288_18443.png Your_Front_End_Framework_is_Overkill_18444_20795.png Your_Front_End_Framework_is_Overkill_20796_21143.png Your_Front_End_Framework_is_Overkill_21144_21191.png Your_Front_End_Framework_is_Overkill_21192_21539.png Your_Front_End_Framework_is_Overkill_21540_22583.png Your_Front_End_Framework_is_Overkill_22584_22787.png Your_Front_End_Framework_is_Overkill_22788_23615.png Your_Front_End_Framework_is_Overkill_23616_24515.png Your_Front_End_Framework_is_Overkill_24516_25667.png Your_Front_End_Framework_is_Overkill_25668_25763.png Your_Front_End_Framework_is_Overkill_25764_26975.png Your_Front_End_Framework_is_Overkill_26976_35339.png Your_Front_End_Framework_is_Overkill_35340_39251.png Your_Front_End_Framework_is_Overkill_39252_40055.png Your_Front_End_Framework_is_Overkill_40056_41375.png Your_Front_End_Framework_is_Overkill_41376_48827.png Your_Front_End_Framework_is_Overkill_48828_50123.png Your_Front_End_Framework_is_Overkill_50124_50195.png Your_Front_End_Framework_is_Overkill_50196_50255.png Your_Front_End_Framework_is_Overkill_50256_50339.png Your_Front_End_Framework_is_Overkill_50340_50423.png Your_Front_End_Framework_is_Overkill_50424_50434.png