00:12 welcome to in relentless pursuit of breasts my name is Derek Brier I'm a development director at papad I work out of our Boston office and I'm super
00:19 excited to be here kicking off railsconf with you all and I do feel like I won the lottery because I get to go first
00:24 and then I get to enjoy the rest of the conference and see all the great talk with you guys without having to worry about this presentation I could give my
00:32 Twitter handle is right up there on the screen so if I feedback during the talk or after the talk you can tweet me there meet me in the hallway later on in the
00:39 week awesome softbox swag to hand out so you can find me later and give out some cool notebooks and potentially some
00:44 t-shirts and things like that so ostensibly this is a talk about rest right so what is it I'm kind of just
00:53 kidding about that I'm not going to recap Roy fielding dissertation here there's been plenty of conference talks
00:58 on this in fact it was alluded to at the opening he knows that this is the twelfth rails comp and at every single
01:04 railsconf there have been at least one presentation about ref so why should this rails comps be any different and
01:11 you know in addition to those conference talks we also have probably hundreds of blog posts developed by the community
01:16 probably I don't know half a dozen books or so and hours of podcast material some
01:21 of which I'm responsible for and a common refrain refrain among a lot of
01:26 that content is that somehow we're doing rest wrong there can be any number of
01:32 ways that we're doing restaurants as programmers a lot of us tend to love semantic arguments and rest seems to
01:39 have plenty of them for us to have so we do rest is all about the power of HTTP
01:46 on some level so there's plenty of arguments for us to have there do you have an API do you version that API with
01:52 a slug in your URL perhaps should you instead be using the accept header and
01:58 content negotiation if you were going to be more restful maybe a few years ago
02:04 now there was a pull request to Rails to change support for or to add support for the patch verb because that was more
02:10 semantically correct than how we were using put and I remember at the time I had really strong feelings about that one
02:15 and I was like yeah we really should be using patch and so now we can and nothing has changed and then there was
02:24 this hyper media it was kind of alternately read as like an extension of
02:30 rest or a rebrand of rest and it was all about providing additional URLs for clients to use to get more details about
02:36 about your resource the big idea being that clients shouldn't be building their own URLs you should you should provide
02:44 them for it for them and then whatever
02:49 this is I think it has something to do with hyper media but to me it just always sounded like mean Cheerios thank
02:58 you so the secret is that none of that
03:04 stuff really mattered as much as I thought it did those really strong feelings I had about patched like I
03:10 alluded to nothing changed when that became a reality none of those things
03:15 make me a happier or more productive developer or make my application more successful most of us in this room I'm
03:23 guessing work on a single app or maybe an API with a small number of clients that we control because we also write
03:29 those clients or we work with the people who do or we have a business agreement with the company that does or something like that
03:35 and in those cases in all cases really it's consistency that matters we can make those decisions that I alluded to
03:41 before and make them consistently and we can move on the rest of those decisions
03:46 are rather academic and that's not to say that you shouldn't care about them at all you should have opinions and you
03:52 should discuss them but I believe that the importance we put on them is outside for their benefit so this is a talk
03:59 about rest so what am I going to talk about I want to talk about how rest makes my code better and my job easier
04:06 how it makes my code easier to read easier to maintain easier to extend and how it can ease rails app growing pains
04:13 that we all experience so that end I'm actually going to spend a lot of the talk talking about nouns and verbs in
04:21 response that's resources and actions so resources being your domain objects and actions being the things you can do with
04:27 them this is the very very basics of rest and certainly it lacks the marketing appeal of something like hypermedia
04:33 but we're going to use our focus on resources and actions to drive us towards creating more small things
04:39 because it's small things small controllers small models small views small objects those are the antidote to
04:46 all of the rails anti patterns that I encounter on application after application so yes in this talk we're
04:54 going to talk about some common anti patterns that I do encounter on a regular basis and I'm guessing that you do as well we're going to talk about how
05:00 restful design helps us to avoid and correct those anti patterns the first
05:08 time I talk about custom actions right there's nothing special about the seven default actions that a rails scaffold
05:14 controller gives you right you got new and update and create and all those other ones
05:21 fielding certainly didn't bless any set of actions maybe it would have been best if he did but he didn't but this is a
05:29 case where strictly following that convention over configuration that David talked about is going to help us to
05:34 avoid many of the pitfalls it's the first step along some long avoiding a lot of these anti patterns before I get
05:42 started with a definitely take a quick second to talk about how I get started in a rails application so if I'm coming
05:48 on to a rails for an established rails application with a very first thing I do is open up route shut RB because a good
05:54 routes file can tell me a lot about your application right it can tell me all of the capabilities of your application and
06:00 do so very succinctly and it can tell me about the language of your app not not Ruby but like the business language of
06:07 your application what are we actually working with a bad routes file also tells me a lot about your application
06:13 tells me where I'm going to find large controllers or which code I'm going to need to I may need to read in order to
06:18 understand what it is your application does so I thought we could start with a
06:23 slice of a routes file that obviously a simplified slice of a routes file but I
06:29 commonly see in rails applications so here we can see on the first line we have a singular user resource so right
06:35 away just from experience that tells me the singular user is likely the current user and we support and edit and update
06:40 action which is them editing their user record or updating the user record in some manner perhaps their user profile
06:46 something like that and then there's these two custom member actions that are just sort of hanging out here they seem relatively harmless but I immediately
06:53 want to know how to edit password and update password how do they differ from editing and updating a user and why are
07:00 they on the user's controller so I immediately want to dive into that users controller and see how things why those
07:06 choices were made but before we do that I want to take just a quick pause and look at what those routes those member
07:13 routes in the middle there would look like if we wrote them out longhand without the use of the resources helper
07:18 they look something like this and I just
07:25 want to focus on the controller mappings there if we break those out we have users edit passwords users update
07:33 passwords and there's a pattern there that pattern is noun-verb down so that
07:39 pattern is a dead giveaway that we're missing a resource and I see this in a lot of applications and then the
07:44 resource that we're missing is actually right there in the action name right the resources password so we have passwords
07:50 edit passwords updates and that pattern is the more familiar noun-verb pattern we're manipulating a password in
07:57 these actions we're not manipulating the user the fact that user is the the fact that password is ultimately stored on
08:03 the user's table is inconsequential to the resource that we're dealing with so
08:08 we can fix this in our routes in our routes file by creating a password resource another singular resource we
08:15 don't need to create a password model for this to work as I was saying and here we put password in its proper place
08:21 of prominence here it is the thing that we're working on it is the thing we're editing it is the thing we're updating
08:26 and we get to use our conventional edit and update action here's what our
08:32 passwords controller looks like all we've done is copy over what used to be edit password and update password into a
08:37 new controller and called them edit and update move them views around updated some helpers so the dark taps path and
08:44 we're ready to submit our first PR at this point there tends to be some questions or possible objections that
08:50 come up a common one is that this can't be worth
08:55 another controller right and I always wonder what I always wonder what is it that a file cost less right it's very
09:02 very lightweight right and I and ultimately my response to this was that I've never once in the many years I've
09:08 been doing rails development regretted extracting a controller I've never wished my controllers were bigger I've
09:14 always wished I had more of them that were smaller so any chance you can take to create another controller you're
09:21 often wise to do so and it's also often a first step towards larger refactorings
09:26 as we'll see throughout this talk the second objection is more of a realization usually not not so much as
09:33 the objections but password isn't a model here as I as I talked about we're so used to there being a one-to-one
09:38 correlation between active record models and our controllers that it can feel wrong somehow to stray between so stray
09:45 from that and as I we talked about the rail scaffold generator earlier and that certainly encourages this one-to-one
09:51 correlation you generate a scaffold you get a model you get a controller you get some views things like that and the
09:56 books and tutorials written about rails often reinforce this when you want to introduce new functionality or change functionality you've just either
10:02 generate a new scaffold or generate a new controller and a model something like that but the key takeaway here is
10:08 that our controllers do not need to map to active record objects one to one our controllers can map to a single column
10:15 on an active record object or to just a plain old Ruby object that isn't persisted anywhere that helps us for
10:20 whatever reason and this realization was a light bulb moment for me and in speaking to countless other developers
10:26 they profess it also was through them as well it's what it's often highlighted is like the one realization that really
10:33 improved people's rails code because what it does is it frees us up to build small objects to bridge between our
10:39 controllers and our models and lets us not expose the specifics of our model
10:45 implementation at our controller layers and controller level and we can see an example of that in our next anti-pattern
10:53 so complex actions I'm talking about here is like really long controller actions perhaps calling out to several
10:59 private not doing something like that they tend to be very difficult to read very difficult to test and
11:06 resistant to refactoring because it's hard to break off pieces of them without messing up some other parts but the key
11:11 thing to realize here is that oftentimes we can rethink complex actions into several smaller actions across several
11:18 resources and this is often appropriate to do the first thing I want to call out
11:24 is that nobody comes into work thinking like I really can't wait to write some controller code today right it's just
11:31 kind of a thing that happens we write complex controllers over time in the beginning our controller actions are
11:37 just the way we like them they're super boring for example we may have a controller action that allows users to
11:43 update the caption on a photo that they've uploaded and that action might look something like this you don't need
11:49 to read every line here right you can just kind of get a sense for what it's doing from the shape of it because you've written the controller like this
11:54 before probably and it's boring it's wonderful how boring this code is right
12:01 I want to see this in every one of our controllers unfortunately it seems as if no boring controller like this survives
12:07 first contact with our users or our product owners if we're not diligent about it before long a new story might
12:13 come along alright this seems pretty harmless as a user I want to mark a photo as featured so it's displayed
12:18 prominently on my profile so my immediate thought here is ok I'm going to add a featured column on photo and
12:24 it's just another column that gets updated just like we had with caption I don't really need to change much at all no problem so we do that and we submit
12:33 that in the product owner test fit and comes back as I I forgot to tell you I should have told you you're only allowed to have one featured photo ok so I guess
12:41 we have to have a conditional for when you go from something that wasn't featured to something that is featured and we need to find the previously
12:47 featured photo and update that so it's no longer featured all right cool we can do that so we submit that and there's
12:54 one more thing that comes back and says oh I was able to under my final photo and I really don't want that to happen
12:59 we should just pick the first photo to be featured all right that seems arbitrary but these things happen
13:08 this is a real feature that I have developed so you know and you might
13:17 think long and hard and best-case scenario you come up with a controller action you update your update controller action to look something like this
13:23 which is kind of intentionally hard to read here it's interestingly shaped right and if we zoom in on the new
13:31 method that update photo private method we've we've extracted there's a lot going on here right we've got an active
13:36 record transaction we've got a compound conditional we have an else--if which just the spelling alone in Ruby makes me
13:43 kind of go hmm I probably shouldn't be using this right and it's not bad that
13:53 whole thing is not bad by comparison to what you're probably thinking of when I say complex action but as a spoiler if
14:00 you're paying particular attention to the code and the requirement this is also not correct and how could it be
14:05 right business logic like this in controllers and conditionals and controllers like this are often not
14:11 tested and as such have bugs in them so how did something so how did a feature
14:17 that seems so simple end up putting us here which again not probably not as bad
14:23 as your complex actions but it fits on a slide the problem is one of differing
14:28 perspectives we wrote our original controller thinking that we were updating attributes on a model where
14:34 each attribute was of equal importance the new feature requires us to treat a certain attribute differently right we
14:42 have to kick off a process one attribute is now more important than the others and the behavior differs based on which
14:48 way that attribute changes whether it's going from false to true or true to false the dissonance in those
14:53 perspectives is what results in the complexity we saw and we can resolve that complexity resolve that dissonance
14:59 by getting back to being boring with rats will introduce a featured flag
15:05 resource to represent flagging and unflagging photos our photos controller goes back to what we previously had it's
15:11 super boring forms that we saw earlier and we're going to make sure our new controller is equally boring and here's
15:17 how that might end up looking it's deceptively it's kind of a deceptively small font here because now
15:23 it's two actions but if we zoom in on create we can see it is almost identical to the boring photos controller we
15:30 showed before the finder changed because the parameter changed and now we're using a service object if you see here
15:37 the add feature flag service object to get the work done but we maintained that
15:42 familiar boring shape of our controller action and the same thing is true of our destroy action we're using a different
15:48 service object or objects Shawn doesn't like service object so here's one of
15:56 those service objects their objects might look like so here's our add
16:01 feature flag service object so you can see this is also pretty boring Li shaped it's not perfectly factors that I would
16:08 RIT as I might write it but it's also not very interesting all of the complexity and the original controller
16:14 or the controller that we showed that have that complexity in it all of that is now gone right the compound
16:19 conditional the if-else it's all faded away into the route right those
16:24 decisions were all made before our controller code even ran so as a result this is also going to be significantly
16:31 easier to task I can unit test this or model test or whatever you want to call this kind of test that your depended on
16:37 the database for right I can test this in isolation somehow and then I can have an overriding feature test that have
16:43 pretty good confidence that this is correct the lesson here is that we need to be boring your controller should be
16:50 boring your model should be boring when I first started in rails it was common to hear fad model skinny controller and
16:56 we don't say that as much anymore because we really want small things everywhere what we should be saying is
17:02 boring model boring controller boring object there's something really satisfying and taking code that was
17:08 complex or perhaps clever and breaking it into something include into component pieces that are boring so as we add
17:15 complexity to the application we want to make sure that the code we're adding is as boring as possible
17:26 now when I'm reviewing a routes file or controller actions I often encounter the third anti-pattern of ambiguous language
17:33 so what I mean by the how many of us out there have an orders controller with a process action or something similar
17:40 right what does process to do what does it mean to process an order that would
17:45 likely depend on who I ask if I ask somebody who works in the warehouse what does processing in order mean
17:50 they're going to tell me it's how they maybe maybe they're gonna tell me that's how they go and pick an order and they prepared for shipment if I ask somebody
17:56 who manage the inventory maybe they'll tell me it's AG no it's actually dispatching that order to the proper warehouse to be fulfilled from or if I
18:03 ask somebody in finance I can bet they're going to tell me its processing the charge for the credit-card charge collecting the money
18:09 this might seem trivial after all we're talking about the code so as long as those involved in the development of the
18:15 project agree what process means does any of this matter ultimately having
18:21 ubiquitous language throughout your application and in the business is what's going to ensure either
18:26 communication about everybody among everybody who cares about that system right what we want to do is avoid
18:32 translating between the business terms and the terms used in the code because that results in confusion and it results
18:38 in people making the wrong change because the product owner asks for it in the language of the salespeople and you
18:44 implemented it in the language of the code so process doesn't tell us anything
18:49 to figure out what it means we have to go source diving so okay let's open up this this orders controller which I'm
18:54 sure is very boring right so again I need to fit stuff onto a slide here so
19:00 the real action in the real controller would be a lot harder to decipher than this but these controllers tend to begin
19:06 with an indecipherable entanglement of conditional before actions at the top and those before actions are possibly
19:12 ordered defendant in worst case scenario which I've seen several times they mutate some sort of instance some sort
19:18 of instance state along the way so we pick our way through all of that and then we drop down into the process
19:24 action itself and that calls out into several private methods which we have to kind of unwind and those depend on
19:29 instant states as well okay so we go through all this process and then we discover that what we're actually talking about is shipping an order
19:35 processing an order is equivalent to ship it so why didn't we just say so so let's just say so
19:42 we didn't say so because this is awful this somehow reads worse than processed
19:48 we're like where are we putting the ship I don't know the problem is we don't we
19:56 don't need a better verb what we need is a resource so let's do that instead we're not putting a ship we're creating
20:03 a shipment this language works even if you're not ultimately inserting a
20:08 database row somewhere you can use create it's fine we don't need to change
20:14 the underlying implementation so here's what our shipments controller looks like now we pull over all the before actions
20:20 we need they're no longer conditional that's kind of nice and you know we take the process action
20:25 and we make that our create action and then we pull over any private method that it needed right just by pull over I
20:30 literally mean copy and paste it right private methods and all everything and
20:36 then we submit this as a pull request to say we've improved the language of the application isn't this great at this
20:42 point we tend to get a little bit more heartfelt in the objection category yeah
20:49 I just told you I copy and paste with a bunch of code so I did duplicate a lot we duplicate a lot of the private
20:54 methods to make it work and some of that private method duplication is just duplicated typing like the finders and things like that I'm not going to worry
21:00 about that but some of it may actually be duplicate knowledge that would be nice to have housed somewhere if
21:06 breaking out that new controller is what it takes to highlight this then it's worth it every single time and I
21:12 wouldn't rush to go ahead and make those extractions now like let them fit for a little bit and make sure they make sense
21:18 this change stands on its own as our friends to any Mets likes to say duplication is cheaper than the rot
21:24 abstraction so I'm going to live with this duplication for a little bit and see where it takes me but this change does stand on its own and the larger
21:32 objection is that I didn't actually improve the code here the ubiquitous language improvement I made though is
21:37 worth a PR and a merge no one else is going to have to wonder what process means we're all going to be talking
21:42 about the same thing consistently as long as we we know the developers often saying process but there's something
21:48 else with value that this is done for I like to call this breathing room right
21:54 it's the best way the best way I can explain is to draw a comparison to writing something writing a blog post or a paper or a conference talk something
22:00 like that and you may in your writing you may have a sentence wedged into a paragraph somewhere that isn't sitting right with you
22:06 it feels important and you want to say it but it's just not working so you try
22:11 to reword it a few different ways but it's still not great and then you pull it out into its own paragraph and suddenly you realize the problem was
22:17 that you had a lot more to say and you can start to expand expand on that and it starts to make more sense in itself
22:24 and it starts to strengthen the things that are around it as well that process is akin to going going from
22:32 something like this in our code right we've got this tangled mess and we're trying to figure out where the steel string goes and so we're pulling at it
22:38 and then we realize oh this is a totally separate piece of teal string over here right and we're trying to make
22:43 improvement on something like this so something more like this we're holding a single piece of thread and we're still
22:50 not quite sure what to make of it but we can pull at it and we can see where it goes so we want to get to this state
22:57 because that's where we can really start to impact the rest of the application right so where do these things often go
23:05 state machine calling state machines
23:11 themselves an anti-pattern is harsh right state machines happen somewhat naturally in a lot of our work orders
23:18 kind of transition among various states of fulfillment pretty naturally my problem isn't so much with the idea of a
23:24 state machine it's more how they're commonly implemented in rails applications they typically are made up
23:30 of hundreds of lines of DSL tacked on to a model and that NAT and that DSL expresses all the possible events and
23:36 transitions and validations and potentially methods that are overridden in various states and that all gets
23:43 tucked into our order model for instance because that happens to be home to the state column and so we just shove it all
23:50 in there a sign that I might be in store for something like this would be seeing this in the rest file when I see this is
23:58 a good indication that I'm in for a large Controller backed by a state machine so I might go ahead
24:04 take a look at that ordered model and try and figure out what's the state machine doing so here's the beginning of
24:11 it okay so I came here trying to figure out what happens when an order is authorized so like okay here are our
24:16 events right here at the top right nope nope those are transitions or don't nope
24:21 they're not transitions they're callbacks for transitions okay alright but all I care again all I care about is
24:27 authorized so okay I see on that third line that's authorized oh but that's going authorize the captured up the
24:34 fifth line is going from pending to authorized that's what I care all right and it authorizes a payment but it does
24:39 it after it transitions I don't know what that means but it should this class know how to authorize a payment right I
24:47 don't think so so here are the various events we support as we scroll down in
24:53 the state machine this one's not so bad there's less than a handful of them great and yeah okay here's our transition when we authorize we go from
25:00 pending to authorize another nice thing about this is like they're very it's a very linear progression among the states so it's not too bad and here's some
25:08 custom class behavior based on the state we have different validations based on whatever state the thing happens to be
25:14 in and we may actually as I alluded to earlier have methods that are overridden or methods that only exist on a certain state here's what the whole thing looks
25:22 like it certainly isn't a pathological case but it's also not boring it's
25:28 extremely dense when I'm reading through this code I'm usually trying to answer a specific question about one particular
25:34 event and I'm left much like in our orders controller example to try and piece together the entire thing by going
25:39 through a thing of callbacks and then the transitions and the states and all that other stuff and is this all tested
25:47 probably not because somebody went I'm sure they test it in the state machine in the state machine state machines are
25:55 magnetic right they attract more states and more transitions and more events and more callbacks and they accumulate
26:00 conditional logic which is where our bugs hide states and transitions that fall out of use are almost never cleaned
26:06 up because no one's clear that they're no longer in use anymore many of the recent projects I've worked on have two
26:12 hundred three hundred four hundred line state machines definitions this is not uncommon I don't
26:17 work on extremely pathological project all the time so how is rest thinking
26:23 going to save us down here all the way in our model still this one from my
26:28 friend Shawn pretend for just a moment that update didn't exist
26:34 what Associated Records would you need to create in order to properly reflect the state of your order those are the
26:41 resources you need to care about so if we did that in our example we might end up with that right we've created
26:47 resources for authorization capture a refund or rejection and we support creating those resources thinking
26:54 resourcefully here gives us that breathing room I alluded to earlier to reconsider the interactions between our controllers in our model each of these
27:01 state transitions can now be encapsulated by an object if we want and the object may still well update that
27:07 state column on order that's perfectly fine or we may actually insert some
27:12 associate records instead also works fine so in addressing each of these
27:22 anti-patterns oh sorry let's talk about this one so what used
27:28 to be an encoded mess of transitions and events is now just like this boring object here so this is this is what it would look like if we extracted that
27:33 authorization thing into an object or service object or process object or command object whatever you want to call
27:40 these things and what used to be a bunch of DSL is now just a boring Ruby class
27:46 and it's boringly shaped and if I want to know what happens when an order is authorized I open up this file and it
27:51 tells me and if we want to change what happens when an order is authorized this
27:57 is so lightweight that there's no sunk cost fallacy to overcome we can throw this away and start again without worrying about losing some sort of
28:05 context that we didn't understand about authorizing in order so anything that drives us towards these types of small
28:11 plain Ruby objects is going to be a win for our rails applications so in
28:16 addressing each of these anti-patterns we thought about our application from the outside in we've been preaching
28:22 outside in or a lot of us have been preaching outside in development for quite some time generally when talking about test-driven
28:27 development but outside in development works equally well when design your domain object interactions and it
28:33 results in similarly similarly better design and better code what we're doing
28:40 is changing the language of the application from what is this application store and how does it store it to what is it that this application
28:46 does at the highest level there's still an overriding objection that I often
28:52 hear too much of the advice in this talk and some of you in this room may be
28:58 thinking it and that's you know this is fine for crud app but my apps are
29:03 different my apps a snowflake it's much
29:08 more complicated than what you're letting on this is fine for base camp but my projects a lot more complicated
29:15 or pretend perhaps maybe I just want to use RPC or whatever something you like
29:21 you don't really like rest that much so what I found in app after app is that in
29:26 most cases what's keeping any app from being just a crud app is a lack of imagination you haven't gone back to
29:34 rethink the problem from the outside in to identify the resources that you're actually talking about and you want to
29:41 be a crud app believe me believe me because crud apps are boring right and I
29:48 hope you know I hope you know by now and I say boring I mean that in the most sincerely complimentary way you want to
29:54 be a crud app because rails is really really good at crud app and you've
29:59 chosen to write or have been stuck with maintaining a rails application so when
30:07 doing that be boring be restful don't worry about response codes right
30:13 identify the real resources and use in your application and design your entire system from that perspective from the
30:19 outside in don't worry about the vagaries of your data model or your data store any questions yeah so the question
30:29 was how would you handle a state by the state machine example sorry the example of a wizard write a multi-step process
30:35 that may be at the end creates or updates one record it kind of depends on
30:40 the specifics of what you're trying to get done but I did recently do the same type of thing where people were going through this register wizard and telling us a bunch of
30:46 information about the facility that they were onboarding and the way we did that
30:51 was have them in step one they created the shell of the resource and in step two we modelled that as like associated
30:59 records even though ultimately it wasn't it so they weren't all associated records some things were like an address would then be associated to the thing in
31:05 the next step and there may be a state thing at the end that happens to say like yes they've checked all these boxes and the wizard is now complete but
31:12 trying as much as possible to think about breaking that up into different resourceful steps and it is kind of
31:18 dependent on the exactly what you're doing in the wizard so the question was
31:23 a common objection is that it's fine to do it's basically fine to do that here but you haven't you haven't addressed it
31:29 everywhere else is that like now now we have a different pattern in use in lots of places it is a common objection
31:36 you're right about that and I I mean we have to be trying to make the
31:41 application better and if people can agree that yes this is better and we should be moving to this then I think
31:48 you do it right and you know you update the other things as you as you have need
31:54 to but yeah there is Ted there does tend to be some pushback about like oh well
31:59 you know now this is a different pattern we have we've never had a service object anywhere now we have a service object but if that's an improvement and the
32:05 team can agree that that's an improvement Fiat the option is just stagnating and a thing that you agree is not the optimal
32:10 solution so you know that's the way I would put it so where I would put so the
32:16 question is where did all the complexity that was in the state machine go when I showed the example of the extractions
32:21 that I had done and I wouldn't extract through a controller what I what I actually expected there to and I
32:27 might've done a poor job of explaining it was that was the service object the controller's going to use and I would put all as much as I could of that there
32:33 right and there was if we go back I don't know how far back that is oh not
32:41 too far okay so there was this like idea of whether or not something's authorized Abul down on the bottom and that would
32:46 be like the conditional validations perhaps and the before transition and after transition stuff that all just
32:52 kind of goes away in the middle of this process or call or whatever you want to call that the main method of this object
32:57 here because it does the transition of updating the order and then it calls the
33:02 authorized thing that was that we were doing in our state machine at that point
33:07 so moving that as much as possible into a service object or a collection of
33:12 objects that work together and testing those individually and I think this read this really does kind of encapsulate a
33:20 lot what was happening in that state machine and I think it's read significantly easier I haven't thought
33:28 about it from that perspective I think the generators are super useful and I use them on occasion like when I need to
33:34 remember what a vanilla controller looks like and I don't know that it's a
33:41 solvable problem if you're going to generate code I don't know that like the generator could know exactly what the best thing to do was oh and for the
33:47 video the question was should should we update the should we update the generators to be more in line with an
33:53 approach like this somehow so the question was about alternative action names like reorder you have a collection
33:59 that if you have a collection of something you want to reorder them so we create a reorder action and how would I handle that and yeah I would typically
34:06 like going back to our photos example if you're reordering all the photos I might
34:11 create an album instance right and you can update that album instance with an ordering of its component photos or
34:17 something like that or a positions controller like you alluded to and your question something like that but there's
34:23 no reason the collection of objects can't be a resource in and of itself so
34:28 yeah that's how I got all that so the question is I'm making and making a
34:33 rails engine is that what I'm doing okay so making an API for an engine and the
34:38 action is start the engine how would I make a nice resource for that boy top my
34:45 head I don't know engine start request create and engine update sure I mean
34:56 that's up to you and your team like I think I don't I'm not trying to say that you should never have a custom action
35:02 but I'm saying it should be your default to never have a custom action and you should agree with your team that like here a custom action makes sense for me
35:08 I just happen to think that answer is almost never but you may differ slightly I just that you don't differ to the point of
35:13 creating custom actions and your orders controller all the time that kind of thing they're laughing cuz that's my favorite question so the question is
35:19 where do you place these things right and I always ask that question because it's so nice when you open up app and you have like models you have this and
35:24 you have that wherever you can put them
35:31 in app services app objects app boring I don't know but just pick a thing I
35:38 worked on a project before where he actually broke them down based on the types of things they were they were like a command object or if they were a query
35:45 object that's a common thing like app queries I'll see for like query for complex bury objects just agree with
35:51 your team what you want to do and use a fuzzy finder like control P in vim to find the file anyway and you're all set
35:59 cool anything else all right thanks