-
ANDREW WARNER: Welcome. I an Andrew Warner.
-
I am the director of engineering at
-
RapGenius dot com. You can follow me
-
on Twitter at wwarner. And you can also
-
follow RapGenius on Twitter at RapGenius.
-
So Tweet at me during the presentation,
-
after the presentation, tomorrow.
-
Whatever. I'm down. I will respond to your
stuff.
-
So, this is really exciting for me. This is
-
my first RailsConf speaking. And so, you know,
I'm
-
super excited to be here. Come on. Little
round
-
of applause. Yeah. Yeah.
-
This is very exciting for me, not just because
-
I'm speaking, but also because you all, you
know,
-
this is a pretty full room. You all chose
-
my talk over the other two talks! This is,
-
you know, it makes me feel good. It also
-
is crazy, because, how do you even know what
-
I'm gonna be talking about? I had some summary
-
that's kind of vague. Like, maybe I'm gonna
say
-
some stuff, but, you know, maybe I'm gonna
change
-
it a little bit. Now I've got this slide
-
on the screen that says Rails Holy Grail.
Who
-
knows what that even means? So, you know,
I'm
-
excited that you chose me even besides all
this
-
stuff.
-
So, you know, I'm gonna be talking today about
-
the Rails Holy Grail. I'm a little bit disappointed
-
that DHH kind of stole my thunder with his
-
Holy Grail slide. But, you know, I, I still,
-
I'm gonna use it. I couldn't find another
replacement
-
Holy Grail slide in the meantime.
-
So, I guess, what am I gonna be telling
-
you about? Well, first, I'm gonna be talking
to
-
you about what the Holy Grail is. So what
-
I mean when I say the Holy Grail. I'm
-
gonna be showing you some existing Rails solutions
that
-
kind of get us close to this. I'm going
-
to be offering up a new solution for your
-
consideration today. And I'm gonna show you
what else
-
this new solution gets us.
-
So, first off, what is the Holy Grail of
-
the web? This background is like the song
Holy
-
Grail by Jay-Z. I don't know. So, the Holy
-
Grail of the web, what I actually mean when
-
I say Holy Grail, is the best possible user
-
experience combined with the best possible
developer experience. So
-
it should be very easy for me to rapidly
-
develop an application, as a developer, that
is also
-
easy to use for a user.
-
And so what is the best possible user experience?
-
Well, I'm talking about sort of a, a single-page
-
app thick client feel. So you shouldn't have
to
-
reload the entire page every time you, every
time
-
the user actually clicks on a link. So in
-
2004, when Rails came out, it was really great
-
because it allowed you to create, very quickly,
websites
-
which were kind of a thin client, where every
-
single click reloaded the whole page.
-
And this was revolutionary. Before that, you
know, it
-
was really difficult to make a site rapidly.
And
-
around the same time, actually, Google released
this Gmail
-
thing. Kind of hard to see the screenshot,
but
-
I think you're all familiar with what Gmail
actually
-
is. Gmail was this single-page app where every
single
-
click actually loaded right on the same page
that
-
you were on whatever you content you wanted
to
-
see as the user. You didn't have to wait
-
for your whole browser to refresh. This is
pretty
-
good. So it's just no full page reloads at
-
all. This is the best experience for the user,
-
and it should sort of feel like a desktop
-
app or a mobile app in terms of the
-
native feel.
-
The best developer experience is a little
bit different.
-
So, you should be able to use a developer-friendly
-
framework. You should be able to rapidly develop
something.
-
You shouldn't have to reinvent the wheel.
Easy things
-
should be easy. So, Ruby on Rails is one
-
of these frameworks. You might have heard
of this.
-
Kind of why we're here today. So you should
-
be able to use a developer-friendly framework.
-
You should be DRY. You shouldn't have to repeat
-
yourself. D-R-Y. Don't Repeat Yourself. But
actually, what I
-
mean here is more like DRV. So what is
-
DRV? Well, I mean, you shouldn't have to repeat
-
views. You shouldn't have to write one set
of
-
views that lives on the client's browser and
one
-
set of the views that lives on your web
-
server.
-
You should be writing mostly one language.
At least,
-
in so far as views are concerned. So you
-
shouldn't have to context switch. Context
switching is very
-
expensive. Sort of switching from Ruby and
Rails to
-
JavaScript. This is difficult for us, as developers.
-
And your website should be SEO friendly. So
I
-
guess this part really applies to content
sites. So
-
I work at RapGenius dot com. Content and SEO
-
friendliness is extremely important for us.
We lost a
-
bunch of traffic when we actually got banned
from
-
Google for a little while. They showed us
exactly
-
how important SEO was. So your site should
be
-
able to show a crawler, a search engine crawler.
-
HTML that it can index and than make available
-
for users' searching.
-
So so what is the closest thing to this
-
Holy Grail today?
-
Well, it's kind of the node.js. There's a
node.js
-
solution that I think is the best thing. Come
-
on, boo node.js! Give me some boos.
-
So there's this Airbnb Rendr framework, right.
So this
-
says render your backbone JS apps on the client
-
and on the server using node.js. So this framework
-
is, you know, pretty easy to use. You write
-
your backbone JS client-side app and the client
can
-
sort of incrementally update the page and
this sort
-
of Gmail-like experience. And then the server
can also
-
render full HTML pages for arbitrarily deep
links. So
-
the user can still see a full HTML page
-
if they get deep-linked, and a web browser,
or
-
sorry, a web crawler for a search engine can
-
also see HTML. So this, I think, is the
-
best solution right there. Right, out there
today.
-
And here, I've actually built like a little
demo
-
app using render to show you how cool it
-
is. So this is a little bit washed out.
-
But, this is sort of a mini version of
-
our site RapGenius. It's, so RapGenius allows
you to
-
view documents and read documents and also
read inline
-
annotations on those documents. And the annotations
are meant
-
to provide context and also explanation, if
something's complicated,
-
and just add to the text.
-
So here I've built RailsGenius, which allows
you to
-
add context to, like, Rails talk abstracts.
So this
-
is my talk. And I've added some inline annotations
-
here, and the, the point I'm trying to make
-
is that we should be able to, when I
-
click this link, to add views, which is actually
-
an annotation, this shouldn't refresh the
whole page. It
-
should just load-in the part of the page that
-
changed. Which is a much better experience
for the
-
user.
-
So if I actually click on this, it just
-
loads that part of the page. You know, this
-
is something that, you know, might be familiar
to
-
you from using apps, but it's, it's kind of
-
hard to like do this out of the box
-
in Rails. And, you know, also you should be
-
able to like edit it right there and that
-
should just snap in the edit view, et cetera.
-
And this should not be too, too difficult
to
-
build. Looks like I lost my internet connection.
There
-
we go.
-
So this kind of stacks up pretty well. It's
-
DRY. We have one set of views. It's SEO-friendly.
-
You know, we can serve HTML the crawlers.
It's
-
a thick-client feel, so single-page app. Mostly
write one
-
language. It's backbone JavaScript, et cetera.
But it is
-
not Rails. So I think it takes, it still
-
took me awhile, even with this render thing,
to
-
like, create an app that was good. And Rails
-
is just much easier to create like, the vanilla
-
example apps using, like, scaffolding or even
not using
-
scaffolding. It's just way faster for development.
So I
-
still think this is bad even though it's the
-
closest thing to the Holy Grail today.
-
But, my point is that Rails, I'm, I'm worried,
-
because I think Rails is kind of getting left
-
in the dust in this respect. Like, it's kind
-
of, there's not really like an established
solution for
-
building like a thick client good experience
Rails app.
-
And so now I'm gonna show you some sort
-
of solutions that get part way there. So let's
-
look at those.
-
So one option, and, you know, this is kind
-
of a joke but it's a serious thing that
-
people actually do, is creating one version
of your
-
app that lives on the client, and one version
-
of your app that lives on the server. And
-
so, you know, in this example you would write
-
erb or HAML on the server, and then you
-
would have an API that returns JSON from the
-
server to the client, and then the client
would
-
figure out how to render new parts of the
-
page that it wants to snap in using like
-
some kind of frontend like handlebar or underscore.js
templates.
-
Right, so this seems kind of reasonable. But
the
-
problem is if you forget to update both templates
-
at the same time, you're gonna end up with
-
some inconsistency between the client and
the server in
-
terms of the logic. And this can be very,
-
very dangerous. It can lead to some hard to
-
suss out bugs and, you know, we all know
-
DRY is a good thing to strive towards.
-
So this doesn't stack up very well. It's not
-
DRY. It's SEO-friendly. It's a thick client.
You didn't
-
write mostly one language, though. You had
to write
-
a bunch of stuff on the client and the
-
server. And we only get a half point for
-
Rails. So you've gotta spend a lot of time
-
still on the frontend noodling around there.
-
All right. So Turbolinks are something you
also might
-
have heard of. You might be thinking, well
I
-
can just do this with Turbolinks. This is
like
-
a one-liner, right? So Turbolinks, the way
it works,
-
is you write just one set of views, and
-
then when the user clicks on a link, you
-
can just pop in the whole new page but
-
save the browser instance. So you save on
this
-
overhead of, like, parsing and compiling CSS
and interpreting
-
JavaScript and, you know, running all this
stuff. It,
-
it's actually kind of expensive to spin up
a
-
browser instance for the client. So you, you
eliminate
-
all that overhead and your client is extremely
simple.
-
You basically have to write no JavaScript.
-
So the problem is that Turbolinks kind of
ends
-
there. There's nowhere else to go. If you
want
-
to snap in, like, just a new part of
-
the page, you've gotta write some kind of
custom
-
controller action that just returns that part
of the
-
page and then you've gotta use like some jQuery
-
soup type thing to like snap that in and
-
then you're relying upon your, your page structure.
So
-
that is not a great solution.
-
But this works pretty well if you're trying
to
-
do, depending on what you're trying to do.
So,
-
you know, this is DRY. It is SEO-friendly.
It's
-
not really like a proper thick client, though.
It's
-
kind of like a fake thick client. Feels almost
-
like a thick client. Not quite there. Mostly
write
-
one language. We've got that covered. We've
also got
-
Rails covered. So this is kind of why Turbolinks
-
is so popular I think. Because it basically
does
-
what you want without much hassle.
-
So there's also this Ember/Angular/Backbone
type movement now. You
-
might have sort of seen, there are a bunch
-
of talks about this. People allude to it all
-
the time. This is sort of the new way,
-
this is the new wave of building Rails apps.
-
So you just have a JSON API in your
-
server, that's it. Your entire app experience
lives on
-
the client, so it lives in JavaScript or CoffeeScript,
-
what have you. And the initial page load,
the
-
first time your user visits the site, they
download
-
like this whole JS app thing, and then that
-
sort of boots up and figures out how to
-
like render the site.
-
And so this might remind you of new Twitter.
-
So Twitter in like, 2010 I think released
this
-
new experience where they were claiming this,
exactly. They
-
were saying this is going to be much better
-
for our users because we can just sort of
-
like snap in a new Tweet when you click.
-
And they actually found that this was kind
of
-
costly. Like, sometimes it would take ten
seconds to
-
render a 140 character Tweet. Because you
had to
-
download like all these assets and then like
that
-
would sort of like boot up, spin up and
-
build the page. This isn't like an actually
good
-
experience for users, at least the first time
they
-
visit the page. It's actually pretty bad.
-
So it doesn't quite stack up great here. It
-
is DRY. It is not SEO friendly, though. Now,
-
there's some tricks to sort of, making it,
sort
-
of making it SEO friendly, but, you know,
for
-
the most part it's kind of hard to make
-
it, you know, allow your app to like serve
-
HTML to a crawler. Now if you're not building
-
a content site, maybe it doesn't matter. But,
you
-
know, my claim is this is pretty important
on
-
most websites. It's a thick client. You don't
get
-
to write mostly one language. Half of it's
JavaScript.
-
So, again, half point for Rails.
-
So the point that I am trying to make
-
here is that each of these things makes like
-
a key, key trade off that we can't live
-
without. So what are we actually going to
do
-
about this?
-
Well, now I'm gonna show you like a new
-
solution that, you know, maybe it's good,
maybe it's
-
not. And actually, this starts with a, sort
of
-
like, admission. So I kind of lied to you
-
before. I told you I built this app that
-
I was showing you before using render which
is
-
this like, node.js thing. But the truth is,
I
-
don't even know JavaScript. I don't even know
anything
-
about node.js. Render. I just read about it,
right.
-
I actually built this app using this new sort
-
of like technique slash library called Perspective.
-
So again, here's the same app. And just to
-
remind you, you can kind of click around here
-
and, you know, things just sort of load. And
-
this is a very simple example, but things
are
-
snapping in, you know, just the parts of the
-
page that are changing. Need to get changed.
And
-
you can sort like edit and save stuff. And
-
we're just sort of updating parts of the page
-
that need to change.
-
And so this is this perspectives thing, which
I'm
-
claiming is better, right. So let's see how
it
-
stacks up on the chart that I just made.
-
It's DRY. It's SEO-friendly. It's a thick
client. You
-
write mostly one lang- I think you see where
-
this is going. And it's Rails. So I checked
-
all the boxes in my own talk. This is
-
a key, key thing. You have to be able
-
to do this if you're gonna speak at RailsConf.
-
You gotta have a chart, checks all the boxes.
-
This is good.
-
So, you know, the key sort of thing here,
-
the key part of Perspectives, is that we want
-
to be able to share our templates between
the
-
client and the server. So like the server
should
-
be able to render full HTML. And the client
-
should be able to like receive JSON and like
-
render a template, right. This is sort of
the
-
appeal of something like render.
-
So, here, you know, let's, let's say we thought,
-
well maybe we can sort of share templates.
Maybe
-
we can share our existing erb templates. Those
are
-
pretty easy to write. So here's like a simple
-
erb template, right. We're just generating
like a link
-
to a user. We're using the name as like
-
the anchor text. We're using user_url helper
from Rails
-
to like generate a link to it. This is
-
pretty simple. You might imagine that using
something like
-
Opal, which transforms Ruby in JavaScript,
you could like
-
pour it your whole server, kind of like, instance,
-
including all these helpers link link_to and
user_url, to
-
JavaScript, and then you could just jump down
your
-
erb template and then that could get sort
of
-
rendered on the client.
-
This might, you know, you might think that
this
-
works. But, actually, you can kind of do more
-
stuff in erb than you might sort of be
-
aware of from simple examples. Like, you can,
here's
-
an example, where I'm actually just running
like a
-
SQL query in an erb template. And this, I
-
think, demonstrates like, the fundamental
difference - yeah, boo!
-
This, I think, demonstrates like a fundamental
difference between,
-
you know, the client and the server, is that,
-
they're kind of in different environments.
Like, the server
-
has access to resources that the client, not
only
-
doesn't have access to but shouldn't have
access to.
-
The client should not ever be able to like
-
hook up to the database and ask some questions.
-
Right, so. And the client is the same. Like,
-
the client knows stuff about the user's browser.
Like,
-
they can inspect local storage and all this
stuff.
-
Like, they're fundamentally different environments.
And so I don't
-
think that any of the existing templates out
there
-
really get you this sort of shared environment
for
-
free.
-
So, the way, you know, so the way to
-
get to a shared template between a client
and
-
a server is to find the lowest common denominator.
-
So, like, if you've taken, you know, calculus
at
-
the graduate level, you might have heard of
the
-
lowest common denominator. It's the way that
you are
-
able to like, if you're trying to add fractions,
-
you can like, multiply the denominator-
-
The point is, it allows you to like find
-
some common ground between, you know, the
client and
-
the server, right. So we need lowest common
denominator.
-
Which is the dumbest possible template. So
we need
-
something that's really dumb, that has, that
basically can't
-
do anything. And so what is that? Well, that's
-
mustache. Mustache are the dumbest templates
out there. Don't
-
tell them I said that. They're probably in
the
-
other room or something. But they're, they're
pretty dumb.
-
You know, you might have heard mustache templates
referred
-
to as being logic-less. I actually think logic-less
is
-
kind of like a bad way of describing it.
-
Because when I hear logic-less, I'm kind of
thinking,
-
like, OK, I can't write like an if statement.
-
There's probably no like for loop situation.
Like, what
-
else can't I do? Well I probably can't do
-
like an if-else, like, you know, the reality
is
-
you can actually kind of do that stuff. It's
-
called a different thing. So I don't like
using
-
the word logic-less.
-
It's more like you can't run arbitrary code.
It's
-
more like no code, code-less or something.
So you
-
can't run arbitrary code. This is the sort
of
-
take away from mustache, right. And so, you
know,
-
this is kind of cool because, because you
can't
-
run arbitrary code, we can write mustache
template renders
-
in all these different languages. So you can
easily
-
render mustache templates in Ruby or JavaScript.
If you
-
want to use one of these other languages,
these
-
are terrible, but I guess you could use like
-
dot net or something if you wanted to render
-
a mustache template in dot net. I don't know
-
what you're doing but you might be able to
-
do that.
-
So, to show you like how to create a
-
mustache template, I want to look at like
a
-
specific example. So here's, like, the RailsGenius
app, and,
-
you know, in the left, lower left-hand corner
here
-
there's like an annotation, right. So this
is sort
-
of annotating the line node.js. And if we
sort
-
of zoom in on this thing, we can see
-
there are a few different components.
-
There's the section of text that's annotated.
So we'll
-
call that the referent. This is like a fancy
-
word for like reference or something. So we'll
call
-
that the referent. That's the line that I
highlighted
-
and explained. And then we'll call this the
sort
-
of body. And you'll notice the body can contain
-
like arbitrary HTML. There's a link to node.js
dot
-
org. A link to Ruby on Rails, et cetera.
-
I'm sort of adding, like, you know, I'm adding
-
hyper media here because it's the web.
-
And then there's this edit link, right. And
so
-
this edit link, you might imagine, should
appear for
-
some users and not others depending on, like,
what
-
your permissions are or what your sort of
situation
-
is.
-
And so mustache, the, the template for this,
the
-
whole template, looks like this. So I'm gonna
go
-
into like the specifics of how I would actually,
-
you know, what this is doing. But here's the
-
template. And to render this, I just need
this
-
hash of JSON data. So I can render this
-
anywhere as long as I have this hash. Key
-
thing to remember.
-
So, if I can't run code in mustache, like
-
I can run code in erb, how do I
-
actually like put data in the markup, which
is
-
like the whole point of templates, right?
-
So you can use these tags. Right, so given
-
this section of JSON, you have a referent
mapping
-
to node dot js, right. We can render that
-
data into this template with a, you know,
inside
-
of a block quote, by using this double curly
-
brace thing. This just says, like, basically,
gsub, or
-
actually not gsub, sub this referant into,
inside this
-
block quote. Pretty simple.
-
So this is just gonna print like block quote
-
node.js, you know. That should hopefully be
fairly self-evident.
-
So if you want to sort of do something
-
where you're printing raw HTML, the double
brace will
-
actually escape it. So that's most the time
what
-
you want. But in this case we're actually
like,
-
you know, we want hyper media in that annotation.
-
So this, you know, actually has an href. An
-
a tag, rather.
-
So we're gonna use the triple brace, which
is
-
another type of tag that says print this HTML
-
raw. So this will actually print out, like,
you
-
know, real anchor tag. Which is, in this case,
-
what we want. So here is the sort of
-
meat of mustache. This is probably the trickiest
part
-
of mustache. There's another type of tag which
is
-
this sort of double brace hash block, right.
-
So here is the block that I'm talking about.
-
So you can see this double brace, and then
-
there's hash edit. This hash is kind of where
-
the logic by another name comes into play
in
-
mustache. So this is going to, if edit is
-
like, a boolean type thing, it's going to
run,
-
or, or go into the block. If edit is
-
true, if edit is like a list of something,
-
it basically is your for loop is the way
-
to think about it.
-
There's one more thing that is like if edit
-
is like a hash, it kind of just will
-
run the intersection if the hash is there.
Otherwise
-
it won't. So in this case, we're just saying,
-
you know, we should show the edit link. That's
-
what edit true means. This is our logic by
-
another name. And then we're actually, you
know, grabbing
-
the edit href from the JSON hash as well.
-
And so this will result in just putting the,
-
printing the edit link.
-
Now if edit were false, it wouldn't print
that.
-
And so you might be asking, like, well what
-
if I wanted to do something else. Like I'm
-
used to writing these if-else statements.
So mustache also
-
has this other sort of tag, which is a
-
carrot. SO there's like double, double squiggly,
double curly
-
brace, carot edit, which just means sort of
go
-
into this block if edit is unset or false.
-
So this is the kind of last tag. So
-
in this case, if edit were false, we would
-
just print can't edit. So this is mustache.
That's
-
basically all you can do.
-
So how does this actually help us? Well, I
-
don't know if you guys remember, but at the
-
beginning of this mustache section, I showed
you this
-
template and I said all you need to render
-
this template is this hash. And I also told
-
you that there's a Ruby library for this and
-
a JavaScript library for this.
-
So I think you might see where this is
-
going. If we have some way of generating like
-
a hash, anywhere, then we can render it, we
-
can ship the template and the hash to any
-
environment and like render it there.
-
That's the point I'm trying to make. So how
-
do we actually generate this hash? That's
the sort
-
of tricky part. Well I'm gonna do some handwaving
-
here and say, well, this, Perspective's library
might help
-
us a little bit.
-
So you know here's a traditional Rails view.
This
-
is like an erb template, right. And so what
-
I'm saying is that if we split this into
-
a template, which is mustache, and a perspective,
which
-
is something, it's a new type of object, then
-
we can just have this data transport thing,
which
-
is just the hash, which is generated by the
-
perspective. And then we can render the template
anywhere.
-
So this is how we render on the client
-
or the server.
-
So what is this perspective thing look like?
Well,
-
as you might imagine, it's a bunch of stuff
-
that specifies what is in the hash. So, here's
-
the whole perspective. I'm gonna dive into
different parts
-
of it. But you can see it's just basically
-
a Ruby object with like some macros thrown
in.
-
That's, that's sort of the goal of the library.
-
It should just be a Ruby object. Plain Ruby
-
object.
-
So you can specify inputs, which you specify
with
-
params. So you can say param annotation, this
perspective
-
expects an annotation as input. You can specify
outputs.
-
This perspective outputs reference, which
is the annotation's referent
-
property. It also specifies body as a key.
And
-
that's the annotation's body as HTML. So this
is
-
gonna be raw HTML.
-
And so properties our output. And so these
are
-
actually just keys in this hash. So we can
-
just turn this perspective object into a JSON
object
-
and then that can be rendered anywhere. So
now
-
that we know what this perspective object
is, it
-
should be pretty self-explanatory how we get
from the
-
right over to the left and render this template.
-
Now you might be thinking, isn't this just
like
-
a fancy version of like helpers or something?
Like,
-
helpers with like a namespace? And it's actually
different
-
because, you know, helpers are sort of operating
at,
-
they seem like they kind of live in their
-
own separate object, like annotations' helper
or something. But
-
actually they're in a global namespace which
can be
-
called from any template at any time. And
so
-
they can kind of like override each other.
-
They also are direct function indication.
So this is
-
just data. This hash in the middle is just
-
data. SO like if you reference a property
twice,
-
you're always gonna get the same value, unlike
a
-
helper, which could theoretically return different
things if you
-
call it different times. SO it's kind of like
-
a safer thing for us as developers.
-
And so to build like an app with this,
-
you can imagine the initial request that the
client
-
makes will receive HTML so the, the server
will
-
say, OK let me take this perspective thing,
turn
-
it into JSON, render in mustache template
and then
-
send that back to the user. And, in the
-
case of like new Twitter, the user would just
-
see the 140 character Tweet rendered. And
in the
-
case of like a web-crawler for a search engine,
-
it would see like the full HTML that it
-
can then index.
-
And then subsequent requests, just like we
would do
-
with like Ember or Backbone or whatever, we
just
-
request JSON from the server and then we render
-
the part of the page that needs to change.
-
So, you the know, the key thing here I
-
think is that HTML is unstructured data. And
so
-
a lot of like sort of Rails patterns will
-
tell you just return like the snippet of HTML
-
from the server that you need and then snap
-
that in somewhere. And the eventually leads
to like
-
soupy code and coupling to like classes on
HTML
-
elements, which leads to a lot of like weirdo
-
bugs that are hard to track down.
-
JSON, on the other hand, is structured data.
It's
-
a lot easier to deal with this, so, you
-
can either render it or you could do something,
-
you know, on the client that's a little fancier.
-
If you want to do, update different parts
of
-
the page, whatever. The point is that it's
structured
-
and it's easy to deal with. And if you're
-
building out like a thick client, you want
to
-
couple your client experience to structured
data, not unstructured
-
data.
-
All right, so I'm gonna do the quick getting
-
started. You know this is, this is sort of
-
about this library, but I don't want it to
-
be all about this library. So, you know, it's
-
just a gem. You can just generate the install
-
for it. That'll like make your app perspectivified.
You
-
can scaffold stuff. You know, you break your
erb
-
templates into mustache templates and a perspective.
And you
-
just add this one line to your controller,
so
-
this just uses a responder to figure out if
-
the client wants HTML or wants JSON, and turns
-
the perspective into whatever you want to.
In this
-
case, it's just, you know, find this annotation
by
-
ID. Use this little macro to create your perspective
-
and pass it the data it needs, which in
-
this case is like an annotation. And then
we
-
can render a JSON version or an HTML version.
-
So what else does this buy us? So clearly
-
this rendering on the client and server thing
is
-
pretty good. But actually, I didn't like set
out,
-
when I was thinking about this, to like build
-
some sort of like new thick client like framework
-
thing that competes with Ember. That wasn't
my goal
-
and I'm still not sure that's my goal. The
-
benefits I'm about to tell you about were
actually
-
like the initial inspiration for like wanting
to build
-
this library.
-
So, number one is separation of concerns.
So, I
-
really hate seeing erb templates like this.
Here's like
-
an erb version of the template I just showed
-
you. So instead of having like a nice edit
-
property, there's often like some logic in
here, if
-
you look at the bottom there, that's checking,
like,
-
whether or not to show the edit link. And
-
this is kind of ugly. It's kind of ugly
-
no matter where it lives. But it's especially
ugly
-
if it lives in a template.
-
And it is so easy to do this with
-
erb, cause, you know, erb literally just means
embedded
-
Ruby. So you can just write anything. Like
I,
-
like I've seen saying. SO like here we're
saying,
-
the person can edit the annotation if they
created
-
or they're like a super admin type, type,
type
-
user.
-
So, mustache and perspectives force you into
this separation
-
of concerns, where you literally can't write
any code
-
in your template. So you have to put it
-
in the perspective, which is just a Ruby object,
-
which is where it kind of belongs. And there's
-
no, there's no love for this in erb land
-
in Rails. You're kind of, you're kind of off
-
in this waste land of like, I guess I'll
-
throw some view logic in here. I don't really
-
know where it's supposed to go.
-
And so this, this leads me to like, so
-
here's the, sorry, here's the perspective
version of it,
-
where actually just generate this edit property
and say
-
whether or not we want to display the link,
-
based on that logic I showed you before.
-
So this also gives you like, testing. So I
-
now DHH was like, you know, shitting on this
-
in his talk. I still think testing is important.
-
Maybe not TDD. But like the point is, if
-
you wanted to test like an erb template and
-
had some logic in this, in it, you would
-
have to like, render, the only thing you can
-
do is render the template. You can't talk
to
-
it. It's not an object. You can't ask it
-
questions. All you can do is render it and
-
then do like a string-match on it.
-
And in fact, I've seen a ton of tests
-
like this. Web driver tests are basically
just doing
-
like, advanced regexes to like figure out
if the
-
logic is right. And this is really bad. A
-
perspective is just a freakin' object. Like
you just
-
new it up and pass it the data it
-
needs and then you can test your logic. SO
-
here I'm just creating a test double. You
know,
-
test doubles are important in testing. Test
double for
-
a user, test double for an annotation. I'm
creating
-
this new perspective and then I'm asking it
if
-
the edit link is true and verifying that it
-
should be showing that.
-
So another thing is caching. So this is like
-
maybe a little bit difficult to motivate,
but like,
-
this sort of like cache digest thing, Russian
doll
-
caching thing is kind of hard for me to
-
like wrap my brain around, right. Like, you
have
-
to, you have to write, sometimes, like a special
-
comment to get the templates to know about
each
-
other. Not as good as just having objects
that
-
know about each other.
-
So if you want to cache an annotation show
-
perspective, you just use this cache macro
and that
-
says, use the annotation as the cache key,
right.
-
And so if you're familiar with, like, cache
keys
-
in Rails, if you're using generational caching,
this will
-
just say, the cache key - hopefully you can
-
see this - is just the type of object,
-
the id of the object, and when it was
-
last updated.
-
So this will like fall out of cache if
-
anyone updates the annotation or if it's like
a
-
different annotation it'll have a different
cache key. So
-
this sort of, hopefully this is, is somewhat
familiar.
-
If you have another template that you're rendering,
like
-
here, this annotation show perspective, is
rendering a nested
-
user slash avatar perspective, so you can
see that
-
at the bottom. You might want to say, well,
-
if the user updates their avatar, we also
want
-
this to fall out of cache.
-
This is sort of the, the Russian doll caching
-
of it all, right. So if the inside Russian
-
doll is uncached then it should bust the outside
-
Russian dolls cache key. So this thing, you
can
-
also assign a cache key to. You can say,
-
cache based on the user. So if the user
-
gets updated from the user's avatar perspective,
we want
-
this to fall out of cache. And so, like
-
I said, we want the whole thing to fall
-
out of cache if the user gets updated or
-
the annotation gets updated.
-
And so what perspective will do for you is
-
say, OK, we know that there's a nested user's
-
avatar perspective here, and so to generate
the cache
-
key for this whole thing, we're just going
to
-
concatenate the cache key from the annotation
and the
-
cache key from the user and produce this ugly,
-
terrible, long cache key, which you don't
have to
-
worry about at any point as the writer of
-
the code.
-
So this is all sort of handled transparently
for
-
you. So are we ready to sail off, to
-
drive off into the sunset in Rails land now
-
with this new stuff? Well, not quite. The,
the
-
point I'm trying to make here is that, or
-
one thing I want to get across here is
-
that this is sort of a nascent library slash
-
weekend project motivated by, you know, having,
making it
-
annoying to like, do caching, and it's hard
to
-
kind of separate your, your templates out,
and also
-
I'd like to be able to like render the
-
same thing on the client and server. But there's
-
still a bunch of stuff to be done, right.
-
Like there's still some work to be done to
-
like integrate this with existing like frontend
frameworks if
-
you want to add like a bunch more rich
-
experiences on the client.
-
And I want to get to the point, though,
-
where we can have a good answer to these
-
node.js libraries. Like this is a big motivation.
Like
-
I'm tired of node.js being, like, well let's
just
-
embrace JavaScript. Like, no let's not embrace
JavaScript. Ruby.
-
Ruby is better. So let's, let's get at them.
-
But, the key take away is you shouldn't be
-
sort of creating one version of your app that
-
lives on the server and one that lives on
-
the client. The ideal situation is move most
of
-
the stuff to the server but be able to
-
like still create this thick client situation.
-
So that's it. That's my talk. You can check
-
out this library by going to RapGenius slash
perspectives
-
on GitHub, or if you're lazy, there's this
bit.ly
-
link. bit.ly slash RG perspectives. And also,
as I
-
said at the beginning of the talk, we are
-
hiring. So if you're sort of interested in
this
-
kind of stuff or other stuff Rap Genius related,
-
get at me. Hit me up on Twitter. Hit
-
me up via email. Andy at RapGenius dot com.
-
And I think we have time for some questions.