Curly - Rethinking the View Layer
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Part Number | 44 | |
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 | 10.5446/30654 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
RailsConf 201544 / 94
1
4
7
8
9
10
11
13
14
16
17
19
21
24
25
29
30
33
34
35
36
37
39
40
42
47
48
49
50
51
53
54
55
58
59
61
62
64
65
66
67
68
70
71
77
79
81
82
85
86
88
92
94
00:00
InternetworkingTwitterComputer animation
00:30
Copenhagen interpretationServer (computing)BitFront and back endsComputer animation
01:17
SoftwareEmailAddress spaceComputing platformQuicksortFile viewerProjective planeWritingDecision theoryComputer animation
02:09
Formal languageTemplate (C++)QuicksortComputer configurationComputer animation
02:42
QuicksortProduct (business)WebsiteRevision controlGraph coloringMathematicsWordArmGUI widgetKnowledge baseArithmetic meanAxiom of choiceFunctional (mathematics)Field (computer science)Process (computing)10 (number)Scripting languageTap (transformer)Social classStagnation pointDefault (computer science)ImplementationVolumenvisualisierungComputer animation
05:45
Template (C++)Drop (liquid)Drag (physics)QuicksortWebsiteDependent and independent variablesExtreme programmingComputer animation
06:30
Connectivity (graph theory)WebsiteMonster groupBitSet (mathematics)Point (geometry)Knowledge baseInstance (computer science)MathematicsQuicksortSurfaceDefault (computer science)Template (C++)Computer animation
07:49
WordField (computer science)Execution unitHypercubeType theory2 (number)Computer animation
08:21
QuicksortTerm (mathematics)Formal languageWeb-DesignerTemplate (C++)Right angleProgrammer (hardware)Position operatorProgramming languageData structureFunctional (mathematics)ProgrammschleifeImplementationPartial derivativeLiquidCartesian coordinate systemObject (grammar)LogicElectronic mailing listComputer programmingMedical imagingReplication (computing)WordEngineering physicsFormal grammarCache (computing)Computer animation
10:41
Mobile appElectronic mailing listFormal languageTemplate (C++)Product (business)MathematicsLinear regressionSoftware testingLogicTerm (mathematics)Server (computing)Condition numberService (economics)ResultantFunction (mathematics)Computer animation
12:06
Different (Kate Ryan album)Template (C++)Poisson-KlammerLink (knot theory)LogicOnline helpForm (programming)Positional notationConnectivity (graph theory)Social classMobile appPartial derivativePresentation of a groupSpacetimeCellular automatonComputer animation
13:02
Poisson-KlammerElectronic mailing listMobile appVariable (mathematics)Normal (geometry)Message passingMappingBoilerplate (text)Overhead (computing)Template (C++)Social classNumberPartial derivativeInstance (computer science)Local ringConnectivity (graph theory)Symbol tablePresentation of a groupRight angleDisk read-and-write headSystem callPlanningComputer animation
15:15
MappingTemplate (C++)DatabaseMechanism designArithmetic meanLogicProduct (business)MiniDiscImage resolutionSymbol tableComputer animation
16:01
Text editorTemplate (C++)Product (business)MathematicsLine (geometry)Traffic reportingSummierbarkeitSource codeComputer animation
16:52
LogicQuicksortSoftware developerForm (programming)Template (C++)Mobile appMathematicsCodeWeb pageMarkup languageFront and back endsRevision controlInheritance (object-oriented programming)Data structureComplex (psychology)BitSymbol tableCodecComputer animation
19:02
Data structureFlow separationState of matterEntire functionLogicComputer configurationPartial derivativeComputer animationLecture/Conference
19:40
MultiplicationPresentation of a groupSocial classGame controllerQuicksortModule (mathematics)Computer animation
20:14
Software testingQuicksortInheritance (object-oriented programming)Computer animation
20:48
Library (computing)Software testingLatent heatVariable (mathematics)MetadataTask (computing)Insertion lossLogicComputer animation
21:43
Software testingCycle (graph theory)Variable (mathematics)Presentation of a groupSocial classWordLogicComputer animation
22:17
Latent heatUnit testingResultantCache (computing)Right angleKey (cryptography)Template (C++)Web browserData structureLogicHash functionChemical equationOrder (biology)RoutingSoftware testingSummierbarkeitLevel (video gaming)Computer animation
23:30
Key (cryptography)Cache (computing)LogicSoftware testingPresentation of a groupTask (computing)Function (mathematics)Hash functionArithmetic meanComputer animationLecture/Conference
24:12
Markup languageData structureWeb browserRight angleTouchscreenReal numberCASE <Informatik>PixelVotingProcess (computing)Computer animation
25:03
BitFitness functionGroup actionComputer animation
25:36
CodeGame controllerObject (grammar)Multiplication signSource codeGroup actionModule (mathematics)CASE <Informatik>String (computer science)Cache (computing)Template (C++)ImplementationStructural loadVolumenvisualisierungCorrespondence (mathematics)QuicksortMarginal distributionInsertion lossComputer animation
27:44
Social classData structureMatching (graph theory)Term (mathematics)Mixed realityProcess (computing)Level (video gaming)CodePresentation of a groupLogicFormal languageQuicksortCASE <Informatik>Perspective (visual)Line (geometry)Template (C++)Thresholding (image processing)Complex (psychology)Personal digital assistantAdditionSign (mathematics)Civil engineeringMessage passingPropositional calculusFlow separationComputer animation
29:36
Product (business)Template (C++)Open sourceReal numberObservational studyWrapper (data mining)Control flowComputer animation
30:29
Multiplication signOpen sourceType theorySource codeComputer animation
30:58
LogicLink (knot theory)Computer architectureVolumenvisualisierungProduct (business)Line (geometry)Form (programming)Right anglePlotterCASE <Informatik>Endliche ModelltheorieSoftware developerOpen setQuicksortMechanism designSocial classTerm (mathematics)Boundary value problemConnectivity (graph theory)Different (Kate Ryan album)Template (C++)State observerAdditionSummierbarkeitPresentation of a groupAsynchronous Transfer ModeComplete metric spaceMultiplicationDescriptive statisticsMultiplication signText editorComputer configurationDebuggerObject (grammar)Domain nameIntegrated development environmentAugmented realityType theoryLecture/Conference
Transcript: English(auto-generated)
00:15
Thank you all for coming here to hear me speak. I'm very honored that you're all here to see me.
00:23
My name is Daniel Schirpek. I go by Dash on the internet. You can find me on the Twitter and the GitHubs and all that. I came all the way from Copenhagen to be here. Copenhagen's not usually like this. Usually it just rains. But I couldn't use a photo of that. That'd be sad.
00:42
OK, so first a disclaimer. There's not gonna be any JavaScript here. I'm very sorry if you thought that. We'll have something that'll look a bit like mustache. So you'll feel familiar if you're looking for JavaScript. I'm not sure how many here do mainly JavaScript front-ending.
01:01
It's fucking a lot. OK, great. So this is all server-side Ruby-generated views right now. It's more like classical EAB stuff. So I'll get into all that later. Just didn't want to disappoint too many people. I work at a place called SendDesk.
01:20
We do customer support software. We are a hosted platform, so you'll get an email address that people can complain to. And it will give you like a nice UI so your employees can manage support requests, all that stuff. This title, Curly, you're thinking of the view layer.
01:43
I'm gonna get into what Curly is. Curly is an open-source project that helps you write great views. However, I feel like there's a nice story behind some of the design decisions, why Curly looks the way it does. And I want to start out by sort of telling you that story
02:04
and then I'll talk about Curly and how it'll make your lives a lot easier. So it all started with how we came to build a new template language and why we did that. It's not something that you typically set out to do.
02:22
It's sort of a pain in the ass. And once you did that, you have to write the actual templates in that language and what if you then decide that it was a stupid language then you have to rewrite all your templates. So it's something you really think long and hard about before you do it. And there were lots of options already. So why do we do it?
02:41
Well, for the last three to four years I've been working on a product that we call Help Center. It complements the main Sendesk functionality which is ticket support. It's a hosted knowledge-based community site and it integrates with Sendesk but it's sort of its own product.
03:01
This was version two basically of an older product that we had that was also a hosted knowledge-based community site but it had several shortcomings. And one of the big shortcomings was that it was very difficult to customize.
03:20
We allowed our customers to upload a custom logo and change some background colors but when users entered the knowledge base it all looked sort of alike, right? And they definitely didn't look like the brand of our customers.
03:40
And our customers were not happy with that of course so we then made the choice to allow them to inject JavaScript into their knowledge base and community site. And that worked. You can do a lot of stuff with JavaScript. And they did. They added custom widgets and they added text.
04:02
They removed features they didn't like and they reordered stuff. They changed the colors, the fonts, everything so that it sort of looked like their brand. It was great and they were somewhat happy but that implementation had some shortcomings. Mainly when you loaded the site
04:21
we would first render the default look and feel and then once downloaded, hit, a bunch of JavaScript would render everything and change everything and things would move around and jump and it sort of felt weird and didn't feel that professional.
04:41
Another big problem was that since our customers were using JavaScript to change things they could depend on anything. They used any class name, any sort of tag name to tie in behavior and to do selectors and move stuff around and that in turn meant
05:03
that we couldn't really change anything about the HTML without breaking lots of customer sites and we had tens of thousands of customers. So it was impossible for us to know what would break for whom when we made a change and in the end it meant that we didn't really update
05:21
that site and we just let it sort of stagnate because it was just too much pain to actually make changes so it looks like something from the early 2000s which is sort of bad when you're trying to sell to new customers also. So we decided that for version two, among other things, we wanted to address that problem. We wanted to have a proper fix for it
05:41
and we had lots of discussions but finally, let me use this, we decided that we wanted direct support for theming and customizable templates. We wanted our customers to help define how the site should actually be rendered when we render things into HTML and should happen up front, not as sort of a thing
06:03
that happens after we deliver the site. So we had lots of discussions about how that feature should work, like what kind of access should people have, how much responsibility should they have and we had like one extreme was that
06:21
we just had a drag and drop thing and the other extreme was that we did everything themselves. And we ended up somewhat in the middle. So the idea was that we provide a set of predefined components and we have default templates that they can just use
06:41
and they look nice and then the customers can go in and change all the HTML they want as long as they don't mess with the components. So the components are just something that they can move and remove if they want to. Maybe they can have multiple instances of them but they can't actually make changes to them. This allowed us to minimize sort of the API surface
07:04
that we had to support to just those components and it made things a bit more manageable for us. Since then, we've learned other things and it's gotten a bit more complex but in the beginning, that's what we wanted to do. So at that point, we had already written most of the site.
07:22
It was functioning and we had the knowledge base on the community. Everything was there. So we sat down and talked about how we wanted to actually implement it. Like how should customers actually do this? We knew that we wanted to actually use HTML. We had asked some of them and there's no reason
07:41
they shouldn't have access to the HTML. So otherwise, they'd just resort to JavaScript again. We didn't want that. So we looked at what we had and what we had was earb. All our views were written in earb and the views that we intended for the customers to customize, they were also written in earb. So the simple thing would be to just allow customers
08:03
to open a text field with the view in it and just type ahead and save and we would use that. And we thought of that for around 30 seconds and then we realized that was the stupidest idea ever and we didn't want to do that.
08:21
So early on, we decided that customers should write templates. They shouldn't be programming. They're not necessarily programmers. They may be sort of web developers but mostly in terms of HTML and CSS and maybe a sprinkle of JavaScript to use DHH terms.
08:40
So we started looking at safe templating languages and there are a few. We were already using Liquid in other parts of our application. So we thought whether we thought about using it here too. So there were a few reasons as to why we didn't do that. Liquid is very cool but it's also very granular.
09:02
It feels almost like a programming language. It's safe to execute but you still have to provide very granular data structures for it to be useful. So we would have to find this huge API of nested objects that we pass to the customers and there would be functions and there would be loops and all this stuff that was just too powerful
09:23
and too advanced for what we wanted. We wanted something that was simple and approachable. Also looked at Mustache. So Mustache, if you do JavaScript programming, you probably know Mustache or Handlebars which I think Ember.js uses.
09:41
It has a very simple syntax, at least Mustache does. Handlebars has added a lot of bells and whistles and was actually pretty close to what we wanted. It's very declarative. There's no logic, there's no for loops. It's just simple. The main problem was that it was not well suited for Rails.
10:03
There was a Ruby implementation but that was completely decoupled from Rails. So we would have to go all in on Mustache. We were not prepared to do that. We wanted something that we could use on just the outer layer of our views. Just the things that our customers
10:21
should be able to customize and nothing else. There's still lots of small partials and other views that we didn't want to convert. We just wanted to keep them as they were. We also wanted something that was sort of baked into Rails and used some of the niceties of Rails such as caching and whatnot which also was a big deal for us.
10:42
So we came up with a list of things that we wanted but we couldn't really find in a language that provided all of it. So we wanted the templates to be safe of course because we were running them and executing them on our servers.
11:00
We also wanted it to be declarative. We wanted our customers to signal their intent in terms of where they wanted to place stuff. Not, they were not supposed to construct advanced stuff. And we wanted to keep all the logic in a separate place. We didn't want to expose that to our customers. We should just decide where to put stuff.
11:21
But all that advanced stuff in terms of generating view related output, all that stuff, conditional stuff, we wanted to keep that out of the product so we could have a simple product and keep the complex data in. And we wanted it to be testable. This would be an API and we would have people
11:42
who depended on it to be stable. So if you made a change and suddenly broke something for a customer, we would get complaints and they'd be unhappy. So we wanted to have regression tests in place so we could make sure that we respected our end of that working.
12:01
And we also wanted to integrate well with our existing Rails app. So we decided to build Curly. It's heavily inspired by Mustache, but it's different in some key ways. You keep all your HTML in templates and you use the curler bracket notation
12:23
to place around components wherever you want them. All the logic is kept in percenters. And percenters are just plain Ruby classes that reside in app percenters. Those percenters have full access to all the things you know from ERB. So you have link help and path helpers and form helpers.
12:44
You can render partials, you can do whatever. And it can be used alongside ERB and Haml. So if you have existing fragments or partials, you can just render those directly from within Curly and the other way around. So it integrates completely into Rails.
13:00
That was very important for us. This is what a pretty simple but also very typical Curly template would look like. You have your components, as we call them, which are just names surrounded by curler brackets and then you have your HTML. So it's very readable and very simple.
13:22
And all the percenters were placed in app percenters. And they're just normal Ruby classes that inherit from Curly percenter. So did you all attend Aaron's keynote this morning? Yes, or did you sleep in?
13:42
So in it he talked about not knowing, like the problem of not knowing which local's view it's using. So if you render a partial template in Rails, the partial may use some local variables and it's very difficult to know upfront what those are.
14:00
So he talked about having to parse itself out. Actually in Curly we decided early on that we wanted an explicit list of variables that a given template should accept and wanted to just crash and complain if it didn't provide that. Because we had run into issues previously where we were like hit by issues around that.
14:21
So we decided we wanted it to be explicit. So actually it's very easy in Curly to just ask a percenter what do we need? And you'll get a list. So here we say well, we expect there to be an article variable pass to me. I'm presenting an article. And then you can just have a number of public methods.
14:43
You can see that article is available as an instance variable. It's magic. So each component maps to a public methods on the percenter class. This is all done automatically for you. A lot of the stuff you could do manually,
15:02
but Curly removes all the boilerplate and all the overhead. And it ensures that each public method there also has access to all the helpers that they need and to rendering stuff. And there's a simple naming convention where each template maps directly to a percenter.
15:25
So we were happy. We used this. It was pretty generic. But we could store our templates in the database. We had some on disk. And then if a customer wanted to customize, we would store their templates in the database. And we were able to inject some resolution mechanism
15:42
into Rails, meaning that we could actually get the templates from there. But we would reuse the same percenter. So that made things a lot easier for us because we only needed to test the logic once. And it was safe and it was very simple. Our customers were very happy and we rolled it into our product.
16:02
And you have an inline editor where you can go and you can change your templates inside the product. You can preview changes. We also allow you to edit CSS and JavaScript and all that stuff. And it's very cool. I was very proud of it when we shipped it. And that's, I think, like two years ago, two and a half years ago.
16:21
And it's been running ever since. So we were happy and we sat back. We were proud of ourselves. We started thinking, you know what? We looked at these templates and the percenters. And then we looked at the rest of our templates that we didn't convert because they weren't customizable. And we started to wonder, maybe this curly thing
16:42
is actually more useful than we initially thought. Maybe it's not just for customization. Maybe it's something that we wanna use more broadly. So just to give you an example, this is actually a simplified version of an actual year B template that I extracted
17:03
a few years ago from our app. I think it's pretty typical. It's not overly simple, but it's not hugely complex either. You could definitely go in and make changes in year B to make it simpler, but hopefully you've all seen sort of this kind of thing.
17:20
So if you look at it, how much of this is actually structured? How much is related to the ordering of things or the HTML? I can help you out here. Not a lot. Most of this is actually Ruby code.
17:41
It's logic that determines how some stuff should be looking. But it's very difficult for, say, a front-end developer to go in and wrap, if you're told, oh, we need to wrap the comment form in a div and give it some class. Well, where's the comment form? Well, in Curly, it's a lot easier.
18:03
Because all the logic has been extracted and identified, which is just as important, you can go in, you can see what is what. Where is the comment form? You can rearrange it, and you can suddenly see where all the HTML is. So that's a big deal, and our front-end developers are very happy about that
18:22
because it made their lives a lot easier, especially if you have big HTML pages containing a lot of markup. If you remove all the logic, all the Ruby from there, you're left with just the essence, just what they need. That was really cool. On the other hand, we back-end developers, because I'm not a very good front-end engineer,
18:43
I should probably say that, we were left with Ruby classes, and we know them. They're things that we can deal in. Like, we can use private methods to clean up stuff. We can use inheritance.
19:01
You can do whatever you want. This is separation of structure and logic, and it really helped us to improve the state of affairs for our entire view layer, which was pretty big. And it basically meant that we could move at a much faster pace.
19:23
We could start dealing with some of the complex logic that had been trapped inside year B. You have some in year B, it's like your option is keeping it there, or maybe extraction of partial, or maybe extracting helper, but none of those options are always perfect.
19:42
Now we can just use Ruby. One of the issues that we had previously was that we sometimes reused some views in multiple controllers, and you had to remember to include the same presenter classes in each controller because a view would need it. So that was sort of annoying, like the controller needed to know what the view needed.
20:04
In Curly, you don't need that because you can just include a module, there's nothing magical about it. Helpers are not special, they're just methods inside a module. And you can use inheritance and whatnot, so that made a lot of this a lot easier.
20:22
So I talked about testing earlier, and testing is a big deal for us. We used RSpec, and we had used view tests previously, and it had been sort of a hassle. Like how many of you do view testing in your Rails apps?
20:43
Yeah, a few. So hopefully some of you know sort of what I'm talking about, but it'd be a hassle. Basically what you do is, you wanna test some specific piece of logic, and you just wanna test that it's either this or that. But you have to actually pass,
21:00
you have to pass all the needed variables to the view, then you need to render it. Then you're giving back this huge blob of HTML, but you're really only interested in just a slight part of it. So you try to use a library proportioning that HTML and getting out that specific tack that you're interested in,
21:20
and then you can then make an assertion of just that. And we found that to be very brittle and error-prone. Sometimes you would test that something is empty, and you think that you're testing the right thing, but actually you're just selecting the wrong thing, and it's always empty, so your test will always pass, and it doesn't really, doesn't actually matter that you have the test.
21:42
So we wanted to change that. So if you look at traditional view testing in a more graphical way, there are three parts. You have the test, you have the view, and you have a poor step. And you have to go through this entire cycle. What we did in Curly was that we just cut out one part.
22:02
We're not actually interested in testing the template itself. We're interested in testing view logic. So we just pass variables to the presenter class itself when we initialize it, and then we just call methods on it. There's nothing magical about it. You can literally just call a method,
22:21
and you'll get back the result, and you can make assertions on just that piece. So that was huge for us. It meant that we could much more easily maintain the API and do specific unit testing. So what we wanted to do is test the logic. We didn't want to test the structure.
22:43
You can test the structure by just looking at the template and seeing the things in the right order, or just opening your browser. Next up is caching. Caching is also a big deal for us. We use Russian doll saw caching. How many of you use that, the caching animal?
23:02
So quite a few. Basically, we have a lot of caches, and they're nested. So using the right cache keys is important for us. And typically in year B, you'd have to specify the top level, cache, and then the cache key, do,
23:20
and then a bunch of stuff in there, and it means that everything is mashed together in this one file, and it's really difficult to test, too. So we wanted to have better support for caching in curly. And we found a pretty good way of doing it. Basically, if you have a cache key method in your presenter class, that view is gonna be cached.
23:40
If it returns a non-null value, it'll cache that view, the output, using that cache key. That makes it very simple. You can have much more complex logic in your cache key and use private methods and whatnot. It also means that you can actually start testing your cache keys. You can ascertain that if you pass in two different values
24:01
for some variable, then the cache key will be different, which is actually a very nice way of testing that stuff. So what I'm getting at is, sometimes it makes sense to use the best tool for the job.
24:20
And there's definitely value in just having like a one size fits all thing. I think that's part of the realist mantra. But in this case, I feel that markup language is actually pretty cool. Like, there's a reason we don't just have a procedural thing that renders pixels on a screen in the browser, right? You send back HTML, and HTML is nice
24:42
because it's markup, you can see structure, it's very easy to identify the constituent parts. On the other hand, HTML is pretty bad for actually writing code, it's not actually possible. So you use your Ruby for that. But I feel that it makes sense to separate the two
25:01
because they are different things. So it's actually fun to see Aaron's talk this morning because he went into some of the things that I've been looking at the last few years and been frustrated at. But he also talked a bit about caching views.
25:23
And I'm not sure how much you know about the internals of ActionView, it took me a while to actually figure that stuff out. But I just want to show you basically how view rendering works and where Curly fits into ActionView. So you probably only deal in action controller.
25:41
You have a controller action and it either implicitly or explicitly renders a view. So you can pass, render some name, or you can just let that name be the name of the action edit or show or something. So what ActionController does is it passes that template name to ActionView.
26:03
ActionView will look around on a desk and it'll try to find that appropriate template. It'll load that and wrap it in an object. It'll then find the appropriate template handler. Usually that's done by looking at the suffix like dot e or dot handle or in our case dot curly.
26:26
It'll then pass the template object to that handler and the handler's actually responsible for compiling that source code into Ruby. And it'll do that and it'll return it back to ActionView as a string containing Ruby code.
26:43
So what ActionView does is it keeps an anonymous module around containing a bunch of methods. Each method corresponds to a view. And it'll take that Ruby code and it'll create a new method on that object named after the view.
27:03
And it'll just put that source code in there and it'll eval it and then it'll call the method. And the method will actually execute the Ruby code and it'll return the HTML and actually then return that back to ActionController. So the nice thing is that the next time ActionView sees that template name,
27:22
it doesn't have to actually compile it because it can just call that method on the module. So that's what Aaron meant when he said caching of views. And this is of course only done lazily and it's done in each unicorn process if you're using this. So there are definitely issues,
27:41
but it's a pretty clever implementation of this. So I've been talking about curly for a little while. So do you think that it's just awesome you should always use curly? Well, no, that's seldom the case. It's not an either or proposition.
28:02
Curly has sold us out a lot, but we also tend to have some complex views. We still use ERB for a lot of cases. Like if you have something that's simple, ERB is great. Like you don't care that things mix in a bit together. Ruby's not about being dogmatic,
28:20
it's about using the best tool for the job. And if you have like a two-line template, there's no reason to use curly for that. Just use ERB. Or if you're in the initial stages of building something and everything's in flux, ERB is great. You only have one file, you can easily move things around. You don't need to have a presenter class and a template match up together.
28:40
But once you read some threshold of complexity, curly is a great way to actually start thinking of things in terms of a proper API and having a proper language for defining the structure. So I definitely encourage you to have a look. As for Haml, I've talked to several Haml people,
29:02
I see Haml as being sort of the same as ERB. It's just from a different perspective. So in ERB, you basically put lots of Ruby code inside your HTML. In Haml, you put a lot of HTML code inside your Ruby.
29:20
But it's basically the same things in terms of like design. You still cut things similarly. You don't separate the structure from the logic. You just blend them in in a different way. So this has been running in production for more than two years, and other companies are also using it.
29:42
A bunch of people in Brazil are using it for some reason, I don't know. So it's been a huge success, and we've open sourced it as curly templates. Someone already took curly. It's a wrap around curl. You can just use curl, but okay. So it's called curly templates,
30:01
and you can just drop it into your Rails app, and it will do nothing. So it's not gonna break anything, but if you then change one of your templates to be .curly instead of .efb, we'll use curly. And you'll have to, you'll set up a presenter, and you'll extract code, and boom, just that one template will use curly,
30:21
and you can use ERB for the rest. So it's very easy to try out and play around with. And I think it's actually pretty cool. So this was maybe a bit short. I think probably have some time for questions if you want to. Just wanna thank you again for coming. And you can go on GitHub, and you actually get this.
30:41
It's open sourced and all that. And you know, pull across the welcome. I really hope that some people will start looking at it, and maybe contributing or finding useful purposes for it. So I think we have some time for questions, if anyone wants. Yeah, so the question was, in our product,
31:00
does the customers know sort of what's available in terms of these components? So yeah, we have a nice augmentation part, and we have autocompletion. So they can just type curly curly, and it'll see a list, and we have descriptions and everything. So that's pretty cool. Yeah, exactly. Within the editor, we have sort of an IDE kind of thing.
31:23
So the question was, in this very astute observer, notice that in one case, there was actually some HTML in the presenter in the form of a constant tag. And that's right. And basically, I don't really care.
31:40
I'm very pragmatic about that. And if you use any kind of link helper or form helper, that's basically the same thing, right? But I think you just want an API that says, I'll return a blob of HTML to you, and you'll actually create HTML in the presenter still. It's just this is logic-driven HTML, right?
32:02
So in that case, yeah, it doesn't bother me. It's still very simple. And if you want a very clean, logic-only layer, then you should create your own presenter objects or decorators outside of curly that don't know about HTML at all. The benefit of curly is that actually it knows form helpers.
32:20
It knows link helpers. It knows all your paths. So you can actually do the clever view rendering stuff. It's view logic. It's not domain logic, right? Yeah. Sorry, the question was that if you want to render a collection, how would you do that? Basically, you can do it in line in curly. You can use render collection something, something
32:41
from the presenter, which will just use a normal mechanism which is rendering a different template multiple times. So you have different options there. And you can also do it in the method itself you want and just return HTML. That's probably messy. Yeah, oh, the question is, what if you want to put classes, if you're generating HTML in your presenter using, say, link two
33:01
and you want to put classes and stuff in there, whether that's crossing some boundary in terms of where the front end stuff should go. Well, I consider presenters to be the front end also. They're just the view logic. They still view code, right? They're not back end code. They're not domain logic. And if you have stuff that sort of smells
33:21
like the main logic, that should probably go into the model or something. But yeah, it depends on your situation. If you have front end developers who don't mind opening Ruby classes, then I would just do that. But if you have a strict requirement of all UI stuff being in curly, you can also do that. You can just have article path something and it returns
33:42
the path and then you just do a ref equals and do the entire thing itself if you really want that. We do that in some cases where we want full access. So both are valid and both are supported. Cool. Thank you.