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.