We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Your Front End Framework is Overkill - Server Side Javascript w/ Rails

00:00

Formal Metadata

Title
Your Front End Framework is Overkill - Server Side Javascript w/ Rails
Title of Series
Part Number
73
Number of Parts
94
Author
License
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
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
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.
AutomationScripting languageEndliche ModelltheorieFunctional (mathematics)Dynamical systemRight angleCartesian coordinate systemWordQuicksortChemical equationDifferent (Kate Ryan album)Web browserArtificial lifeSoftware frameworkData conversionInformation technology consultingBitDependent and independent variablesComputer configurationWebsiteDebuggerRaw image formatStandard deviationWindowSoftware engineeringImplementationGame controllerAndroid (robot)Hash functionLink (knot theory)Group actionCommitment schemePresentation of a groupMobile appWeb pageInteractive televisionData structureElement (mathematics)Point (geometry)FamilyServer (computing)Step responseArithmetic meanMultiplication signProcess (computing)Real numberOcean currentGraph (mathematics)SpiralFormal grammarProjective planeFormal languageMedical imagingAreaAbstractionMetropolitan area networkVolumenvisualisierungPlanningSubsetSystem callCASE <Informatik>Query languageLogic synthesisAtomic numberCharge carrierKey (cryptography)Set (mathematics)Staff (military)Object (grammar)Interior (topology)CodeComputer animation
Source codeProcess (computing)QuicksortCuboidFunctional (mathematics)Computer animation
Dynamical systemSoftware frameworkPoint (geometry)CuboidWhiteboardGroup actionPartial derivativeAreaTable (information)SineSource codeTheoryRight angleFront and back endsArtificial lifeComputer animationPanel painting
Set (mathematics)Form (programming)VolumenvisualisierungArtistic renderingComputer animation
Arithmetic meanGame controllerObject (grammar)Right angleComputer animation
FlagForm (programming)ImplementationBitComputer animation
Front and back endsGame controllerSign (mathematics)Arithmetic meanServer (computing)Standard deviationComputer animationSource code
Template (C++)Row (database)Group actionRight anglePartial derivativeProcess (computing)TouchscreenCuboidScaling (geometry)Table (information)View (database)VolumenvisualisierungEscape characterMessage passingDynamical systemSystem callComputer animationSource code
Right angleGame controllerShape (magazine)File formatDefault (computer science)Template (C++)Commitment schemeComputer animationSource code
Boom (sailing)Cycle (graph theory)Video gameDefault (computer science)ImplementationForm (programming)Client (computing)Game controllerProcess (computing)Performance appraisalQuery languageSocial classBitComputer animationSource code
Remote procedure callForm (programming)NumberQuery languageSlide ruleWordDifferent (Kate Ryan album)Dependent and independent variablesEvent horizonSoftware frameworkSeries (mathematics)Scripting languageRaw image formatAliasingImplementationProcess (computing)View (database)SummierbarkeitBitPartial derivativeSet (mathematics)Order (biology)IntegerCartesian coordinate systemEndliche ModelltheorieBenutzerhandbuchTemplate (C++)Real numberLatent heatFlagType theoryElectronic visual displayClient (computing)PlanningMereologyGroup actionGame controllerOnline helpCoprocessorCycle (graph theory)Category of beingCodeJava appletProper mapEscape characterElectronic mailing listInsertion lossSpacetimeExterior algebraRight angleWebsiteFiber bundleSystem callError messageSoftwareTerm (mathematics)
Game controllerSound effectEndliche ModelltheorieImplementationData storage deviceArtistic renderingMessage passingMultiplication signBitVolumenvisualisierungFunction (mathematics)Line (geometry)Standard deviationPartial derivativeDirection (geometry)Right angleProcess (computing)Dependent and independent variablesInterpolationLocal ringProxy serverScripting languageGroup actionClient (computing)Error messageView (database)Step responseUser interfaceMereologyLevel (video gaming)Server (computing)Data managementLoop (music)Functional (mathematics)Hydraulic jumpSoftware frameworkCodeDifferent (Kate Ryan album)ResultantSelf-organizationRow (database)Electronic mailing listEscape characterTemplate (C++)TouchscreenInternetworkingResponse time (technology)Connected spaceInsertion lossComputer animation
Connectivity (graph theory)Different (Kate Ryan album)Template (C++)Figurate numberPoint (geometry)WordComputer animation
Different (Kate Ryan album)BenutzerhandbuchError messageVolumenvisualisierungEndliche ModelltheorieGroup actionCycle (graph theory)Student's t-testVideo gameLevel (video gaming)View (database)TrailInteractive televisionSocial classQuicksortCodeWebsiteException handlingPartial derivativeCorrespondence (mathematics)Multiplication signPay televisionMetadataElectronic visual displayClient (computing)Series (mathematics)Software frameworkServer (computing)Standard deviationContext awarenessBlock (periodic table)Decision tree learningCartesian coordinate systemSoftware developerDataflowLine (geometry)MappingDependent and independent variablesAreaTemplate (C++)Process (computing)Element (mathematics)State of matterTable (information)Reduction of orderHypermediaSinc functionFunction (mathematics)Event horizonWeb pageVideo game consoleLoginMobile appPrincipal idealDivision (mathematics)Total S.A.Computer animation
Transcript: English(auto-generated)
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, 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, like 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, and 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. And then I had a secondary experience where we went to
Wells Fargo. We were opening a joint account right before my wife and I got married, and the banker asked me, he said, hey, what do you do for a living? I go, yeah, I'm a software engineer. His eyes light up, and he goes, hey, what language? I go, Ruby. He goes, oh my god, I wrote a few
scripts to kind of automate some of the balances I need to know at the end of the day. It was like the second, where the fuck am I at? And so I really, I really missed those sorts of interactions and such, but yeah, and so 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, and great experience. And so when I got there, I went to a company called Z-Vents, and we eventually got acquired by StubHub, and then after that, I ended up striking out on my own doing consulting,
and so I just had these whirlwind of experiences when 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, so that's just a little bit of a background about me. So 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 the implementations are kind of 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 it's going to take care of a lot of the browser idiosyncrasies and differences and such, so that's always the go-to on a lot of projects, and we start to get these higher structure layer of abstractions, right? We have Backbone that's going to give
us a little more structure to our front end. We have EmberJS that we're getting even further with all of its nice conventions and such, and then we have the directives with Angular that are really, really powerful, and they give us even more structure to our app, and then there's kind of 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, and so the point is, right, that everything has its place, and that the front-end frameworks certainly have their advantages, and then we also have the server-side JavaScript rendering, which we're going to show where its advantages
are and where it shines, and so 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, and we'll go from there, so. But first off, we have to qualify
this, right? For anybody who's been with Rails for a long time, I'm not talking about RJS, and I think a lot of people still call it RJS, and this is probably maybe
a problem with the evangelism of this particular subset, but if you guys remember, it depends on how far back you go with Rails and the history, but there's functionality called Ruby JavaScript, and 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 an action and such, and we have our page dot replace HTML, and so we would get these JavaScript requests, and then we'd get this
page object, and we were able to either replace a particular HTML element or we were able to update an HTML element, and 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
like 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.
And I was looking at my Agile books, and I think the Agile two still was citing RJS, and so I assume around it was Rails three that we started to see just the standard JavaScript sort of side requests, but someone else can correct me.
So, 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 freeform JavaScript responses, and so I think this is going to be better demonstrated with some code, and so let's
see what we can do here. All right. So, I have this application. This is just a standard
Rails new. Is everybody okay on that? Can everyone see? And we just have a user model. We just have a name on it. I've already done like the db migrate on it, but that's about it. That's all we're at, right, at this point, right? And so, what I would
like to do is currently we have this functionality. This 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, right? 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. Let's see if we can create some magic here. Let's just do that. Okay. So, first
I'm just going to apply an ID to the T body of our 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. And 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, let's take that, sure, save it. So now we've got our sweet partial, right?
Let's go here. Let's make sure it's still rendering. Nice. All right. So now we've got our partial set up. 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. 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. 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. All right. Nothing. So we don't have anything. So let's see.
Let's see what's going on in the back end here. All right. We can see we've posted to users, and it was hitting users controller create as a JS, right? 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 like 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. So we'll just
say users, and we'll say data pin, 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, right? 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 and we're going to render out. So now we'll call this create.JS.ERB. So that's implying it's
right. Now let's say, okay, try this. Let me say, oh no, nothing happened. So maybe there's something went wrong with my JavaScript. Let's take a look where it fell down. Let's
see. Okay. Use the control, okay, it's JS, commit. And then it's just going to try to get user controller shot. All right. So we forgot one thing here. We've already
used this controller on the create. We want to make sure that it's going to render the default JS template. And so we're just going to go ahead and plop in the format.JS here.
Now let's try this again. Boom. So now if we take a look at the lifecycle of this we have, we posted the users, we process 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's
a little crude. All right. So just to reiterate, this is not RJS. This is way more free form. This is just raw JavaScript with ERB processing, and that raw JavaScript is just getting sent client side. So it's getting that template. It'll get processed by your template
processor. It could be handled, it could be our ERB. And since this is action view, 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 site called todo MVC that has a todo 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 network request. All right. So if we 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 todo list here. We're
appending our list item. You can see the escape JavaScript method has properly escaped all of our quotes. We're just reinitializing our entry for the todo 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 todo. And we're just setting the remote true flag on it, similar to that initial implementation that we walked through. Here's our model. Pretty trivial model. Just have a couple 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 shortened code within your JS templates. But the most relevant portion is just this todo list.
We're just appending. We're rendering out our todo. And then we're just going to go ahead and reinitialize 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 helper call and see it expanded, we would see that the action is set to todos. 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 has ended up true, we're just going to go ahead and do a rails.handleRemote. 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 disabling controls, re-enabling controls, doing proper error display and such.
Here's our controller action. You can see the todos controller create 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
Haml as well. You can just do a regular string, and it provides the interpolation right there, so you can still do the escape JavaScript, render, and still do that same output under Haml. Here's the final portion. When jQuery, 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 calm that wolf. She 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 todo app, and then we have on our ng submit the other directive for an add todo. We come over here, we look at our controller, and this is taken
directly from the todo MVC implementation. We just have our add todo. We're saving. I have a couple of promises here, and it persists that out depending upon what store you have, whether it's API or local storage. Here's the services that provides that insert
function for the store, and they're just posting to the API's todos. It's important to note that this is, 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. That's definitely on the todo list sometime. Not now. That would be boring.
We've got with our Ember.js implementation, we've got our inline handlebars and inline
handlebars template. It's a 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, where because these templates are implemented in JavaScript, we can immediately render it to the screen regardless of what the result is. We could take that chance if we wanted to. That's certainly an advantage
where it's hard to compare that even to a 50 millisecond response time server-side. 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 graceful error retries. 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. This could be totally transparent to the end user, so you have that level of granularity. With the client-side, you have that level of control.
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 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 an eval fails silently. So if you happen to have a problem
with your JavaScript, and you just have this little typo in there, and we go ahead and we're going to say, try this three, and we say create user, oh no, it just fails, and there's nothing. There's no guidance, 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 threw their 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 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 lifecycle
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 Dart. I remember there's 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'll 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. 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. It's slated
for 5.0. I don't know if it'll make it in, but it's been tagged, so excuse me. 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 rebind those events. If you
had 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 rebind 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 and update it at, and then within that update it at, we could just go ahead and rebind those very events that we had set up first. Some of the advantages for JS responses. Obviously, since we're in action view, we
get reuse of partials, so you can see in these two different examples, we've got append, and we're rendering out our user partial, and then within that, for that same resource on our update, if we were doing an asynchronous dynamic update, we could 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 action view 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 certainly could
constitute a reduction of JS, depending upon what you're doing. And there's also, 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 on. Alright, finally, and 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. So thanks you guys, I really appreciate it.