Trailblazer: A new Architecture for Rails
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 | 76 | |
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/30713 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
00:00
Computer programming
00:42
Row (database)Social classEndliche ModelltheorieComputer animation
01:13
Row (database)Object (grammar)State of matterForm (programming)Attribute grammarSystem callComputer animation
02:17
BitSheaf (mathematics)Regular graphMappingHuman migrationSlide ruleLecture/Conference
02:51
FamilyDifferent (Kate Ryan album)GradientLecture/ConferenceComputer animation
03:22
Computer virusGroup actionSpeech synthesisLecture/ConferenceComputer animation
03:53
Digital photographyCASE <Informatik>Web 2.0Physical systemSoftware frameworkQuicksortEmailMeeting/InterviewComputer animation
04:30
Service-oriented architectureView (database)Java appletCartesian coordinate systemAbstractionPoint (geometry)Level (video gaming)Goodness of fitBlock (periodic table)Game controllerEndliche ModelltheorieMathematical analysisProcess (computing)MereologyComputer animation
05:34
Installable File SystemView (database)Cartesian coordinate systemCodeLevel (video gaming)Endliche ModelltheoriePoint (geometry)Game controllerBitProgrammer (hardware)Standard deviationStaff (military)Moment (mathematics)Computer animation
06:24
Mobile appArithmetic meanCodeExterior algebraCartesian coordinate systemAbstractionService (economics)Service-oriented architectureObject (grammar)Enterprise architectureAsynchronous Transfer ModeEndliche ModelltheorieAbsolute valueMoment (mathematics)Right angleDigital photographyComputer animation
08:13
Enterprise architectureGoodness of fitObject (grammar)System callLogicGame controllerGroup actionLevel (video gaming)Attribute grammarEndliche ModelltheorieBitCodeWeb applicationCodeMereologySystem administratorField (computer science)Form (programming)Variable (mathematics)SubsetVolumenvisualisierungString (computer science)Cellular automatonContext awarenessSocial classACIDTask (computing)AuthorizationFile formatSerial portStatement (computer science)Computer programmingCASE <Informatik>Text editorDecision theoryDifferent (Kate Ryan album)Filter <Stochastik>Cartesian coordinate systemAuthenticationResultantProcess (computing)Domain nameStructural loadMessage passingPartial derivativeConfiguration spaceView (database)Software developerBookmark (World Wide Web)Installable File SystemLocal ringDisk read-and-write headWeb 2.0Computer animation
13:31
Online helpLogicPoint (geometry)Cartesian coordinate systemData structureOpen sourceSoftware framework
14:02
DiagramRankingCartesian coordinate systemAbstractionData structureEndliche ModelltheorieView (database)Game controllerValidity (statistics)BitTransport Layer SecurityLogicForm (programming)Task (computing)Video gameInformation privacyWater vaporProgram flowchart
15:56
Slide rule2 (number)Execution unitMereologyLogicGame controlleroutputEndliche ModelltheorieView (database)Cellular automatonMedical imagingSocial classSoftwareValidity (statistics)Domain namePartial derivativeRow (database)GUI widgetObject (grammar)Design by contractPattern languageInstance (computer science)Demo (music)Context awarenessProcess (computing)Different (Kate Ryan album)Form (programming)System callSoftware engineeringDomain nameMoment (mathematics)ResultantOnline helpACIDAssociative propertyCodeNumberComputer animation
20:49
Level (video gaming)Endliche ModelltheorieView (database)Game controllerState of matterComputer animationJSONXMLUML
21:40
Computer fileProgrammer (hardware)Projective planeFunctional (mathematics)Game controllerObject (grammar)Instance (computer science)Endliche ModelltheorieView (database)BitDirectory serviceData structureDomain nameTransport Layer SecurityGroup actionCartesian coordinate systemLogicPresentation of a groupCASE <Informatik>Different (Kate Ryan album)CodeService (economics)Electric generatorWebsiteCone penetration testValidity (statistics)Civil engineeringOnline helpSystem callAuditory maskingTwitterLevel (video gaming)Computer programmingComputer animation
24:32
Right angleSlide ruleMereologyGroup actionEmailGodType theoryTerm (mathematics)InformationWindowBlogPerspective (visual)TouchscreenPhysical lawReal numberSocial classJSONXML
26:24
AuthorizationMachine visionForcing (mathematics)GradientProcess (computing)NamespaceRow (database)Term (mathematics)Execution unitComputer fileEndliche ModelltheorieWordGame controllerTouchscreenQuality of serviceCategory of beingWikiDesign by contractPRINCE2SpacetimeForm (programming)Ideal (ethics)Directory serviceState of matterObject (grammar)CASE <Informatik>Mathematical analysisError messageRight angleInheritance (object-oriented programming)Traverse (surveying)Social classLine (geometry)Variable (mathematics)Sound effectGroup actionField (computer science)Macro (computer science)outputFlow separationPosition operatorData structureInformationAssociative propertyNumberProjective planeValidity (statistics)Different (Kate Ryan album)Point (geometry)EmailVector potentialLogicCodeCellular automatonLatent heatBlock (periodic table)NP-hardSubject indexingNatural numberCodeHorizonView (database)Configuration spaceAreaBitSoftware repositoryObject-relational mappingComputer fontRoutingSystem callGoodness of fitSource code
35:43
AuthorizationValidity (statistics)Inheritance (object-oriented programming)Object-oriented programmingComputer animation
36:13
Inheritance (object-oriented programming)Content (media)Different (Kate Ryan album)Attribute grammarConfiguration spaceCategory of beingFunction (mathematics)LogicRepresentation (politics)PlanningPattern languageDesign by contractComputer animation
37:02
Validity (statistics)Endliche ModelltheorieProcess (computing)Inheritance (object-oriented programming)Digital photographyConfiguration spaceAuthenticationAreaSystem callWordComputer animation
38:10
Representation (politics)Design by contractObject (grammar)Polymorphism (materials science)MereologyComputer animationProgram flowchart
39:04
FreewareDigital electronicsAuthorizationOpen sourceComputer animation
39:44
Data structureLogicGoodness of fitProcess (computing)ArmComputer animation
Transcript: English(auto-generated)
00:13
Hi guys, thank you very much. So, first of all, I have to clarify that the talk title in the program is wrong.
00:22
The talk is called Trailblazer, New Architecture for Rails, and not see you on the trail, because I'm not gonna talk about hiking. I have no idea how this title got into the RailsConf program, but anyway, you're here and that's great, thank you. I'll get you started, no worries. So, I have a question before we start the actual talk.
00:43
It's a serious question. I have a problem with active record. So, I have this post class, and I have this comment model, and they have a has and belongs to many relationship. So, a post can have a lot of comments or many comments.
01:02
And my problem is when I create a post, yeah? The post is, the post is persistent already, and then I add comments to that post. How do I prevent active record from automatically persisting the new state of this post?
01:20
Because I don't want the comments to be persisted yet. So, I have tried this, and it saves the comments. I've tried this, and it saves the comments, and I've tried this, and it saves the comments. So, can anyone here explain how I can prevent active record from saving the comments until I call save.
01:41
.build, but .build calls .new internally, doesn't it? The problem is, and that's a serious question, guys, because we have this problem in reform that when we set up collections internally and then assign them to the collection attribute,
02:02
like comments, it saves the entire object, and I don't want this. So, if anyone has an idea how to prevent this, please hit me up after the talk because I'm desperate, and I don't want to read through all the active record documentation. I could just ask Aaron. Okay, let's talk about Trailblazer. So, before I came to Atlanta,
02:22
I was traveling a little bit to conferences. So, the last stop before Atlanta was in Vilnius. Actually, that's wrong. I was in Minsk, so that's the wrong Google Maps. I was in Minsk in Belarus. It was a great conference, great speakers. We had a couple of drinks, and it was fantastic.
02:44
Before that, I was in, I just confused the slides. So, before that, I was in Vilnius. That's in Lithuania at the RubyConf. It was a great conference, awesome speakers. We had a couple of drinks, it was awesome. A couple? Before that, I was in Poland at the Wroclaw Conference.
03:02
Wroclaw is beautiful. There's churches and cathedrals, or cathedrals and churches. I have no idea what's the difference. It's a beautiful city. It was a great conference, great speakers. We had a couple of drinks, it was awesome. Before that, I was in Brazil at the Tropical Ruby Conference. Has anyone here been to Brazil yet?
03:22
It looks like this. It was, that's a beach, like palms and stuff. Hey, come in, hello. Don't be shy. I don't bite. Brazil, yeah, Tropical RubyConf was an awesome conference. We had awesome speakers, had a couple of drinks. It was great.
03:40
Before that, I was in Mexico and Oaxaca. Oh, boy. Great place, so I gave a talk at a user group about Trailblazer. This was amazing, the community is incredibly cool. We had some good speeches, had a couple of drinks. I learned how to dance Cumbia, it was awesome. And before that, I was in Australia because I actually live in Australia. I'm from Germany, that's where the accent comes from.
04:02
And I'm not gonna show you photos of Australia because it's beautiful and you should all come and visit me there. Okay, let's talk about Trailblazer. Now, let's talk about Rails. We're all doing Rails, right? Yes. This is a RailsConf. So, Rails is a famous web framework,
04:23
just in case you didn't know. It's famous for its monolithic, sorry, integrated system architecture. This is a monolith and this is a service-oriented architecture. Whatever, so Rails comes with a, what are you doing here on my stage, by the way?
04:43
I'm just chilling, dude. Cool. It's all good. Welcome to Atlanta. Thank you. Okay, let's get back to Rails. Rails MVC, we all know it. Like, it gives us three abstraction layers to implement applications, the so-called model, the so-called controller, and the so-called view. And that's awesome because it is quite a simple setup,
05:02
a simple level of abstraction so you can get up and running applications within minutes. You can build a block application in, I don't know, 15 minutes or what's the, what's the, what was your official selling point of Rails? Well, whatever, so you can get 10 minutes, thank you. So you can get up an application pretty fast. You can, you can implement stuff
05:24
without thinking too much about encapsulation, about like not that nightmare that we had in Java and all this stuff. So that's actually great in Rails. So you get it up and running in minutes. The problem is that you only have three abstraction layers and all your code goes into views and all your code goes into controllers
05:40
and all your code goes into models. And this usually ends up like this. And the problem here is that the original selling point of Rails was, hey, let's have conventions and let's have standards. But once the application gets a little bit more complex, you have no idea where to put this code.
06:00
So one of the major problems in Rails is programmers asking, where do I put this kind of code in Rails? And what ends, so we end up with like huge models, skinny controllers that still have seven levels of indentation and all that kind of stuff. And nightmare views with ifs and els and conditioners and all that stuff to make them reusable. So the problem is this monolithic architecture
06:23
for me is not enough. This is the monolith that David showed in his awesome keynote. I couldn't find the original photo, so I draw a picture. This is a camel on the right-hand side. I think I'm, I mean, come on, I'm an artist, right? I shouldn't talk about coding, I should paint.
06:43
Maybe not, no. Who is this guy? You already asked me that. By the way, if you fall asleep, we have stuff to throw at you, so please stay with me and stay awake. So the monolith in Rails. The problem is I don't have a problem with monolithic architectures at all.
07:01
Like I don't wanna deploy seven Rails apps when I just wanna solve one problem, okay? So the thing is, and I think DHH got this wrong, is that monolith, the only alternative to a monolith is not a microservice architecture. We have, I don't know,
07:22
like the monolithic architecture doesn't mean put all your code into one Rails application and that's it, a monolith can be a service-oriented architecture itself. Like you can have services inside of a monolith. It's just about abstraction layers.
07:42
So when I say monolith, I'm talking about one Rails app, but it can be a beautiful, object-oriented, well-destructured architecture in a monolithic application. So please, when we talk about monolith and microservices, don't think of this is a physical app and this is five physical apps because you can have services in a monolith. And the problem, but the problem here is,
08:03
I was just talking about having objects and services in a monolith. The problem is in Rails, or in the Rails community, when you start adding new abstraction layers to MVC, people automatically blame you for being too enterprise or you were over-engineering and this is too many objects, I don't,
08:20
like this can't be good, this has to be slow because objects are really expensive. I mean, every string is an object in Ruby. So yeah, so my problem is that Rails, we say Rails is simple. I mean, that's, every Rails developer says that. Actually, it's easy because simple is subjective
08:41
and easy is objective or something like that. So I got taught in Lithuania that this is a wrong statement. So Rails is easy. That's every Rails developer. However, Rails is easy. It allows me to structure complex applications easily. That said, no one ever, because it is not true.
09:00
It's not funny. So what happens in Rails? In a classy Rails, I'll just walk you through the classy symptoms I've seen in a lot of Rails applications. My job has been refactoring Rails applications for the last 10 years. It was a tough job. A lot of tears, blood, but also tears of joy.
09:21
So let's check out a classy controller in Rails. We got filters that add logic for handling different contexts, for handling authentication, all that kind of stuff. Then we have model code. Every controller I've seen has a lot of model code, instantiating, creating, I don't know,
09:40
changing attributes. Then we have, again, contextual logic. Deciders, is someone signed into this? Is someone not signed into that? So there's code handling different contexts in the controller action. Then we have callback logic, like do this if that happened, and after this, do this. So it's a load of business logic in the controller action.
10:02
And then we also have rendering code sitting in a controller. I mean, this is a controller action. This is a beautiful controller action. I've seen controller actions with, like as I said earlier, seven levels of ifs and els and do this and that. So this is what happens, because we chug in all the code into the controller, or, my favorite part, into the model. So in models, we have configuration for forms.
10:24
I mean, I know we don't use Azure Accessible anymore, but we define fields for forms, and we have accepts and as attributes to handle form submissions and to handle deserialization. But we only have one form per model, because we don't have context. And then people add ifs and els to configure that,
10:43
oh, I need this form in that context, and I need this form in that context when I'm an admin. So I've seen horrible deciders in active model, and also we have callbacks sitting in the model, callbacks that get triggered, sometimes they get triggered and you don't want it, and sometimes you want them, but they don't get triggered,
11:01
and you add ifs and els, and it is a nightmare, because we collect all code in one asset, in one class. And of course, there's also business logic in the model. So everything sits in the model. And I mean, Vue, I'll just run through that, because that's my favorite part of Rails applications. We have helpers and access to models, and access to seven levels of attributes of models,
11:22
and we have deciders that decide about the context, and if it's an admin, render this, if it's not an admin, render that. So lots of code, and then we have helpers that are supposed to help, but they usually are a nightmare, because they pass around 200, wait.
11:41
There you go. Oh, it was supposed to hit your head. He plays baseball. Okay, so helpers, helpers never help me, because what I end up is I pass a million variables and objects to nested helper calls, and we have, again, deciders to decide the context. We have render partial this, pass in locals to that.
12:02
It is a nightmare. So when you look at a classy web application, it doesn't matter if it's Rails, or if it's Sinatra, or whatever, it boils down to the following requirements that we have per request. So the first thing is we have to dispatch, we get a request, and we have to dispatch,
12:21
is it HTML, do this, is it JSON, do that, in case you have a document API. Then we usually do authorization. Is it okay to run this request? Is it okay to run this logic? Then we validate the incoming data. Is it okay? Is it all in this format that I want? Is the user allowed to run this task
12:40
and so on? Then we actually run the business logic. So this is where you run your actual domain code, and then usually stuff gets persisted after you run the business logic, and in the end, we render a result. So it's not that hard. It's one, two, three, four, five, six steps of things that we handle in a request.
13:03
But in Rails, the controller handles, I don't know, parts of that, and then the model handles part of this stack, and they also overlap, so you have model code that should be in the controller, and you have controller code that should be in the model, and then the view does a little bit here and a little bit there,
13:21
and sometimes it does a little bit more, so we have a lot of overlapping code there. It's not clear in Rails, where do I put my code? What's the place for this kind of logic? In Trailblazer, which is a cool new framework, open source, by the way, so you can check it out, and it's got the best book cover ever.
13:42
Do you recognize people in it? I just got taught that this one is DHH. I like this. So in Trailblazer, we have, the point of Trailblazer is take these, we got these six steps of logic in an application, and now take this and structure, give me a structure,
14:01
help me structuring my Rails application, and basically, this is Trailblazer, so I could just go and leave, so this diagram took me about 10 hours to do. It was a lot of work. Do you have a few drinks? I had a couple of drinks, yeah. A few, yeah. So in Trailblazer, we introduce a couple of new abstraction layers shown in this diagram,
14:24
and I'm gonna walk you quickly through the concept. After this, we are gonna have a live demonstration by my friend, Jay Austin. How do you pronounce your last name? Huey. Huey, and you're gonna learn a little bit about how to structure Rails applications
14:40
using the Trailblazer approach. So the first thing I mentioned is that the old layers are still there, so we still have controllers, we still have models, and we still have old-fashioned Rails views if you want that. Trailblazer is non-intrusive, so you can use it, you can use it partially, you don't have to use every layer, and you can use it where you feel you need more abstraction.
15:01
So you don't have to use Trailblazer across your application. Of course, I would love to see that, but whatever. So in Trailblazer, we got the following layering. So now it is clearly visible which layer is responsible for which task. So what we do in Trailblazer is we introduce operations.
15:22
Operations are your business logic. And an operation is not a monolithic beast. An operation internally uses forms, uses forms for validation and deserialization. You use representers, you run your manual business logic in an operation, and operations also have access
15:42
to models. But controllers only access operations, and views only access operations and models. So there is a clear layering in Trailblazer which layer is supposed to do what. I have this new technique in my talks.
16:01
Whenever this slide comes, we do a breathing exercise. It's very simple. So you inhale as much air as possible. You keep it for two seconds, and exhale. It's great. All right, how does it work? I have no idea.
16:21
The controller in Trailblazer ends up as a really, really slim dispatching asset, yeah? So there's no business logic, no persistence logic, no validation, no callbacks in controllers. The controller simply dispatches to the operation.
16:40
So this ends up with really, really slim controllers. And this is my favorite part. The model in Trailblazer is empty. All the model does in Trailblazer is it defines associations, and it defines scopes. So basically, we used models the way models were supposed to be.
17:01
This is active record. This is active record by Martin Fowler, because per definition, and I don't care about definitions of patterns usually, but active record was supposed to be a persistence layer without business logic. And this is what we have in Trailblazer. You can still have business logic in your model if you want that, but per definition,
17:21
we say don't put it in the model. And we also have views. We can still use Rails views in Trailblazer. So you can still use Haml and ERB and all that kind of stuff, because it's awesome. I don't know, some people don't like Haml, some people don't like ERB, but that's another story. You can still use helpers, you can still use partials, all that stuff,
17:41
but we offer you something new. It's called cells. Actually, it's not new, it's 10 years old. It's cells are view models. So view models help you to encapsulate parts or the entire view into objects. We call it a widget in software engineering, and this is what is missing in Rails
18:02
in the vanilla Rails stack. So a cell, ironically, is called using a helper. Yeah, but all that happens is a dispatch to the cell class. I'm not gonna go into the detail of cells, but you have a class that represents a part of your view. And this class can render a partial view.
18:22
In cells, we call partials views because there is no difference between views and partials because everything is a partial. The partial is logic-less, as I call it. So you still use Haml, you still use ERB, you can still use helpers, but you only call methods in your view.
18:40
And the cool thing is, if you call a method like body or avatar, this method is called on the cell instance. So we don't have this problem that we have in Rails with view context anymore because the cell is the view context. So if you call methods in a cell, it's getting called on the instance. It's really, really helpful to replace helpers and to have an object-oriented approach in your view.
19:04
And as you can see, you can still use image tag and URL for and all those great helpers, simple form, whatever, in cells because that's what makes Rails awesome, the view helpers that actually help. But we don't have this distinguishing between, this is the controller context, this is a view anymore
19:21
because everything is just an object. And the brand new thing in Trailblazer is the business logic called operation, the domain layer. And operation is a class. Again, man, so many classes. I don't know where to put all those classes. And operation consists of a contract
19:41
a contract to deserialize and validate input and business code, yeah? So the contract is defined in the operation. The contract is just a reform class. I'm not sure if you know reform. Reform is a form object gem for Rails and we use reform in Trailblazer to deserialize and validate data
20:02
without touching the model. So operations always have a form object. The actual business logic happens in one method called process and that should be the only public method in that class. And in that process method, I mean, we're probably gonna walk through that in the live demo which is still in preparation.
20:26
So the business logic, the actual logic your domain consists of happens in the process method. And so you still access models, you still save models but a lot of work is already done by the operation.
20:42
For example, validating and assigning the data to the actual model is done in the validate call. If you want that, you don't have to use it but I like it. Again, what the, okay, one, two, three. I should start doing yoga
21:00
and have a deep professional voice. Okay, so the last thing in this introduction is I quickly wanna talk about high level architecture because whenever people ask me what is Trailblazer, I say, it is a high level architecture for Rails. What is a high level architecture?
21:20
Well, a high level architecture is everything that sits between the request dispatch and the persistence. That is what I call a high level architecture. This is where Rails leaves you completely clueless because there is no high level architecture. There's a controller, there's a model and there's a view. And what we have to learn is
21:41
we have to think in our domain and not in controllers and not in models. So as an example, every application has functions. Functions a user can perform. Like you view, I don't know why it's a shop. Like you view a shop and then you can add a comment to this shop and then you can follow the shop.
22:01
So stuff, when you click through an application, that's functions, yeah? And in, I don't know, in domain driven design, I have never read the book but apparently this is what we call a use case. And in CQRS, I have no idea what it stands for but it's great. This is called a command, yeah? So apparently there is existing science
22:21
about these concepts. So and in Rails, what we have is use cases and commands get implemented in controller actions a little bit, a little bit in a model and a little bit in view and maybe a little bit in your handmade service object and maybe a little bit in, I don't know, your presenter object and it is a mess.
22:40
And when I, people tell me, Rails is so simple. You can hand over a project and the next programmer is gonna understand everything. This is not true, this is wrong. Like I've seen lots of Rails projects and every project looks different. I mean, great, I know where the controller sit. Great, I know where the model sit and I know where the views are but where's the business logic? How do you structure that kind of stuff? It is a nightmare.
23:00
And what Trailblazer does is it introduces the operation so you clearly know where is my business logic and what's the structure because every operation should have the same structure. Validation, deserialization, business logic, callbacks. And also an operation is not just one crap thing that has one model. So an operation can have multiple models
23:22
and an operation is also not a monolithic beast as I said earlier. An operation is a composition of objects that help you to handle your request. And it's an orchestrating instance in your architecture. And the coolest thing about Trailblazer is that it has a new file structure.
23:43
So instead of cluttering files into app controller, blah, blah, blah, app view, blah, blah, blah, app model, blah, blah, blah, you have one blah, blah, blah folder and it's called a concept. So in Trailblazer we structure code into concepts, comment, thing, I don't know, invoice generation.
24:00
That's all concepts. And all the code goes into that folder that has a couple of benefits. For example, if you rename something, you don't have to rename four directories. You only have to rename one directory, but that's only one benefit. I find it way more intuitive to go through that directory. You see, okay, we got view models. Okay, we got operations. Okay, here's my model. Okay, here's my, I don't know, like helpers.
24:22
And also the views for the view model sit in this directory. So it's way more intuitive to grasp what a concept is doing in Trailblazer. Yeah, Austin, that's you, you're right. Do you want to show us some Trailblazer in action?
24:40
Yeah, I can, I can do that. But you only got 10 minutes. Well, thanks to you, yeah. This is really unprofessional. I usually prepare every slide so I don't have to do this kind of stuff, but he wanted to be part of the talk, so it's all his fault if things go wrong now. Yeah, sure, uh-huh, yeah. I see what you did there.
25:01
All right, guys. So, as Nick said, Trailblazer is actually, it sits on top of Rails, as we know. It's, the one thing I like about it is that, as he said, you don't have to abandon your typical Rails architecture the way that you like doing things. So what I did was I basically built a very simple blog,
25:20
okay, because it's a blog. Everybody knows how it works. You know, it's a classic example. So if the thing will do what I want it to do, it's not moving the window. Stupid technology. All right. Live demos, oh my God. Hey, quiet, you. Anyway, because I went full screen,
25:41
I'm an idiot for that. Okay, so I built the awesome blog of awesomeness because, yeah. Anyway, so the idea, obviously, it's very simple. You know, you just create a blog post, you know, type in information and title, blah, blah, blah. And I just, for fun, I just said, you know, this is markdown enabled. He's extremely proud of this markdown feature.
26:01
I like it. I like markdown. It renders on the front end, so. It's implemented in Ruby, what? Let's see, anyway, see. Just pop my email in here. Anyway, so, creates a post, blah, done. Grabs your Gravatar and all that jazz. Anyway, so that's the basic idea that I implemented here. Now, we've all done this in Rails. This is very simple from, you know, perspective of Rails.
26:21
It's, you know, not a big deal. But in terms of how we did this in Trailblazer, as Nick said, the controllers are really skinny, very tiny, as is the font on this damn thing. I saw you yawning. Thank you, thank you. All right, so, okay, big deal here.
26:40
Post controller, obviously, we have, you know, your index and all this stuff. New, okay, so if I'm gonna create a new post object, what we're doing here is saying, we're calling this form method on post create. Well, what's this post create nonsense, right? This comes from the concepts directory, and of course, underneath concepts, I've just got post and a file called crud,
27:02
which create, read, update, delete. So in here, I'm just requiring Trailblazer operation crud. Most of this is documented, by the way, on Nick's blog, or excuse me, wiki on the GitHub project for Trailblazer. And in the book that I'm gonna mention in a minute. Yeah, yeah, he wants you to buy his book. Buy his book.
27:21
Anyway, so we've got basically, we're just saying, we're subclassing right here. So we've got post inherits from active record. We've got a create class, hence form post create. And one thing I have to mention is, just because we reuse the post namespace, which is an active record model class, does not mean that the operation create
27:40
does know anything about active record. It's just reusing a Ruby namespace. This is a big confusion, there's a lot of confusion in Trailblazer in the community. People think that create now is inherited from active record or something. No, we just reuse a Ruby namespace. So this is how you create namespaces so you can have classes in classes. It's a great trick to have readable namespaces.
28:02
Right, and good class inheritance as well. So that kind of brings up a question that the community might have. Given the fact that what you just said, we can namespace it in this way, what is the potential in the future for separating Trailblazer from active record? Say I wanna swap in another ORM or no ORM at all. What do you think? I mean, is that something on the horizon?
28:21
What's up with that? Well, Trailblazer is not limited to active record, but in an ideal world, you had a post namespace that's not a model. Then you had your operations in that namespace and you had the model that's called, for example, persistence. So you had post, colon, colon, persistence. That's my ideal vision. But in Rails, models are on the global namespace.
28:42
So that's my trick to reuse this namespace. But ideally, it's a real namespace and you have the persistence sitting in that namespace. And then you can replace it with any kind of ORM you want. Right on. Okay, so that explanation out of the way here.
29:01
Basically, like I said, you can look over the documentation he's got. But what we're doing here is this is a contract and this is kind of the meat of kind of what provides, some of the stuff you've probably seen, like validates, for example, usually goes in the model. But in this case, we're telling it, look, you got a property of a title, body, a teaser, which is doing a little caption waiver, author. And of course, in this case, we're doing nested relationships
29:21
because the post has one author and the post, or excuse me, the author belongs to a post. In terms of active records, macros here. So as you can see here, has one author, belongs to post. Okay, so we've seen these associations before. Empty models.
29:40
Exactly, empty models. There's no logic in there. It's, other than that, it's pretty, pretty vanilla. So of course, we're doing properties here inside this block. So what's going on here is this is how we tell the Trailblazer that hey, by the way, you've got this thing called an author and by the way, it's got these two different properties, name and email. This is what gives us the ability to put this inside the form later
30:02
and I'll show you that code in a minute. Of course, here we have validations. I'm just validating presence so you don't fail to fill it out. Now, this is kind of the big deal right here. This process method is going to, as you can see here, it's got this validate block. It's basically gonna make sure that all your params that you pass into it are indeed valid.
30:21
If so, it will call save on it. So that is kind of how we manage the persistence in this case. Now, there are a couple of things that, and I'm gonna ask Nick to explain this in a minute. We had to overwrite a few active record methods as well. We were looking at doing the inherit, or the, what do you call it? Nesting for the... Yeah, so the operation doesn't know anything about,
30:42
I mean, it doesn't know about the structure of the nesting, but the operation does not know how to create, for example, how to create the nested author of the common. So you have to provide that manually. I mean, there's ways in Trailblazer that actually implement this for you, and you can just configure it. But in this example, we explicitly create the author
31:01
to have this nested model set up. Exactly, so we've had- All details explained in the book. Right. So in other words, that's basically, we had a, it's a little bit of a trick to get around some stuff with active record. Anyway, so that is exactly how that piece works right here. Same thing inside updates. So we're still inside the post class, or excuse me, we're inside the, yeah, we're inside the post class.
31:22
I'm getting a little confused with my own code here. Nice throw, buddy. Sorry, I'm an asshole. I wasn't gonna say anything, but, just kidding. Hurry up, you got three more minutes. Okay, four. Yeah, you're an asshole, yeah. Anyway, all right, so anyhow,
31:41
we're still inside our post class here. We've got a class called update inherits from create, so we can also call an update action on this later if we want to. I didn't write that inside the actual, you know, the architecture for it, you know, forms and all that jazz, but you know, you get the idea. So we also had to call set up model here and overwrite it, but it's an empty method in this case.
32:01
So moving on here, as you can see, the post controller, new, so we're just saying form post create, done. Create, run this operation, post create, do. Okay, and I'm just passing in a block. The block is only executed when the validation was successful, so that's the only information the operation exposes, is I was run, and I was successful, I was not successful.
32:22
So the controller does not know anything else unless you do that, unless you extend the operation. It's only true and false. Okay, so anyway, we're basically running this run post create. I'm terrible at naming variables, so I just call it x. Anyway, redirect to x.model, so in other words,
32:40
this could be, you know, there's no hard coding of okay, post or whatever else it might be here, just call model and that's it. So we've got RESTful routes set up in this case, of course. And of course the return here, I just don't want anything to happen if this actually works. So as opposed to rendering the new action here. Show, as you can see, is one line,
33:01
present, post update. Okay, cool. The actual update method as well, same thing. Edit, all that stuff. So, and of course, like I said, I didn't implement all the different things here. So the point is that the controller really just delegates to the operation and handles HTTP specific stuff like redirects, because that's not a concern
33:21
of the operation. The operation doesn't know anything about HTTP and the controller doesn't know anything about the business logic. That's the whole point about this structuring. Right, so what does that say, what? What happens if it fails, when the update fails? When the update fails, then the block is not hit, so you don't have this return redirect to. The block is only executed when it's valid, and then the form is re-rendered.
33:42
Like, just as you do your controller actions in Rails. So the whole point is the block is only executed for successful operations. Exactly, so if this particular thing doesn't work, it's gonna be like, oh, well, nevermind, I'm not gonna bother with this next piece of code. Oh, here we are, render action, new. Okay, done. So we've got the object accessible inside the form
34:02
or inside the view, and we can then look at the errors on the object, just like ActiveRecord. In fact, I'll show you if I can actually see the screen. Let's see, views, is it? Sorry, I don't even have it mirrored over here for whatever reason. All right. Because he's unprofessional. Quiet, you. All right, so, index for posts.
34:22
All I'm doing is just grabbing the posts, and pretty simple stuff, right? Okay, we've all seen this before. Here is our form. Okay, so I'm just saying if the number of errors objects is better than zero, then yeah, we got problems, blah, blah, blah, we've seen this before. Now, in this case, I'm using simple form. Basically, I saw some of Nick's documentation. I was like, okay, I'm just gonna totally rip this code
34:42
and work with it like that. So as you can see, it's very simple compared to existing ActiveRecord or existing Rails, very much the same thing. You've got your inputs, you've got all this stuff. Now the inheritance fields for author. So of course, the form object represent based on post, and now we have the author object off the post and so on.
35:02
So there's the inheritance. And of course, the show is very simple as well. It's just, you know, view code. That's kind of it in a nutshell. There's a few other things, but I'm gonna let Nick take this back. Now there's a little bit of a configuration you might have to do, much of which is documented. It's github.com slash apodonic, A-P-O-T-O-N-I-C-K,
35:21
and then you'll find the Trailblazer repo from there. It's just Google for trail, Google rocks. Yeah, you could do that, yeah. Yeah, thank you very much. So that was awesome, thank you very much. I'm just wrapping up in the next two minutes.
35:43
So the thing is we have, as you saw, in Trailblazer, we can easily have nested setups. So like the nested form, we have, you know, we nest the author into a comment and all that kind of stuff. So that's really, really helpful, and all based on the reform gem. So we have nested validations as well, cleanly implemented, and it's great.
36:07
A lot of things in Trailblazer are based on inheritance. So we use object orientation the way it was supposed to be. Yeah, so we, by the way, inheritance, I didn't know if you know that, but if you can roll your tongue and your sibling can't, then it's not your sibling.
36:23
But, so this is my sister. Apparently, I don't know, maybe you've got different parents, whatever, let's talk about inheritance. So in Trailblazer, you can, operations inherit from other operations, and you inherit the contract, you inherit the representer, all that kind of stuff is cleanly inherited into the subclasses.
36:43
And you can also, Trailblazer's made to, makes it really easy to override specific aspects of the inherited stuff, like you can override properties in the contract, or you can override, you can also override nested attributes in the contract, you can override stuff configuration from the representer, you can override your business logic, it's just using plain Ruby inheritance.
37:03
And the way callbacks in Trailblazer work is also very, very straightforward. So you remember this validate, and then we saved the model. So usually, this goes into the comment model in Rails. In Trailblazer, this goes into the actual validate or process method, so you can call
37:20
callbacks explicitly, or you can use the dispatch, so you define which callbacks to call. And the cool thing is, let's talk again about inheritance, is that, also, I didn't know that if you have a gap in your teeth, your siblings are supposed to have a gap as well. I don't have a photo to prove it, but this is also wrong, because my sisters don't have a gap in their teeth.
37:41
Let's talk about inheritance. So the cool thing is, the cool thing is, you can also deactivate callbacks in inherited operations. For example, in update, I might not wanna have the check spelling callback to be called, so I just skip it, so it's really declarative and simple to override behavior.
38:01
And so, inheritance works with contracts, representers, policies, we also have policies and authentication in Trailblazer, I did not talk about this today, and I'm sorry, and it is also good to inherit configurations. Representers are awesome, they render and parse stuff, so this is helpful for operations when an operation does handle JSON, yeah? So the internal contract can build a representative,
38:25
the representative helps you to work with JSON, all that kind of stuff, so an operation can parse and render JSON as well, if you want that, it's awesome. And again, Trailblazer is not a monolithic beast, it is an orchestration of objects handling every aspect of your request.
38:41
And people say we don't need this, we do this on our own, I agree, but Trailblazer is an attempt to establish a standard, okay? So we get awesome stuff in Trailblazer, like polymorphic operations and policies and blah, blah, blah, blah, blah, it's great, check it out. There's an awesome book, it's on leanpub.com slash Trailblazer, leanpub.com slash Trailblazer,
39:02
leanpub.com slash Trailblazer. Or you could Google it. We also got stickers, the cool thing about the stickers, if you don't like Trailblazer, you just cut it off here and then you have a free Ruby sticker. Ha ha ha ha ha ha ha ha. Nice. So hit me up, I'll give you a sticker. Maybe. And the cool thing is Engine Yard sponsored me
39:22
to come and give this talk, so they basically pay everything, they are awesome, they are really nice. I'm not affiliated with them, but I find it a great thing and other companies should adopt this to support open source authors because it is great if you can speak at a conference and you meet awesome people and a great company stays behind you and supports you.
39:43
So thank you Engine Yard and just to wrap up, use Trailblazer, it gives you new structure layers, use operations because they help you structure business logic, use all my gems and be nice to each other. Thank you very much. Bye.
40:02
Good job, good job.