WEBVTT 00:00:16.800 --> 00:00:18.400 ANDY MALEH: Sorry everybody. I lost the slides. 00:00:18.400 --> 00:00:20.560 I had to reconstruct them right now. 00:00:20.560 --> 00:00:24.280 Right, like in ten minutes. 00:00:24.280 --> 00:00:26.560 Ultra light and maintainable Rails wizards. 00:00:26.560 --> 00:00:29.880 Who has written a wizard in their lifetime? 00:00:29.880 --> 00:00:34.490 OK. It's, it's almost like the most common web 00:00:34.490 --> 00:00:40.400 use case, yet it's the least under, under-valued with 00:00:40.440 --> 00:00:44.670 regards to providing patterns for doing, like, writing good 00:00:44.670 --> 00:00:47.350 code in order to provide for maintainable wizards. 00:00:47.360 --> 00:00:52.620 A lot of the time, people write, like, multi-step 00:00:52.620 --> 00:00:54.010 wizards, where they end up doing a lot of 00:00:54.010 --> 00:00:57.680 copy-paste between the steps or between a bunch of 00:00:57.680 --> 00:01:00.350 controllers. And that makes it a hell of a 00:01:00.360 --> 00:01:02.650 problem to maintain that code a year or two 00:01:02.650 --> 00:01:04.280 later. And every code base is, you know, meant 00:01:04.280 --> 00:01:06.570 to be created for a year at least. Maintenance 00:01:06.580 --> 00:01:09.360 cost is what's really expensive. It's not, you know, 00:01:09.360 --> 00:01:11.580 I can write a wizard in two weeks but 00:01:11.580 --> 00:01:13.360 will I be able to maintain it cheaply over 00:01:13.360 --> 00:01:16.890 a year. And that, that's really why I'm giving 00:01:16.890 --> 00:01:18.970 a talk about this subject. 00:01:18.970 --> 00:01:22.120 So just to give you an overview, I'll be 00:01:22.120 --> 00:01:25.800 talking about, why do we even use a wizard? 00:01:25.800 --> 00:01:32.280 Provide an example. Some implementation goals. The 1001 wizard 00:01:32.280 --> 00:01:36.370 implementations out there. And, finally, I'll talk about what 00:01:36.370 --> 00:01:37.950 I think is a good ultra light and maintainable 00:01:37.960 --> 00:01:40.250 wizard approach. 00:01:40.250 --> 00:01:45.110 So first of all, we don't want to overwhelm 00:01:45.110 --> 00:01:47.530 the user with a huge form of information, kind 00:01:47.530 --> 00:01:49.910 of like those government forms that we have in 00:01:49.940 --> 00:01:55.810 Canada. So I come from Montreal, by the way. 00:01:55.820 --> 00:01:58.790 This is painful on a computer screen. Computers should 00:01:58.800 --> 00:02:03.370 enable people to do better than actual physical paper. 00:02:03.370 --> 00:02:05.320 So one way of tackling this problem is to 00:02:05.320 --> 00:02:10.979 divide it into multiple steps in a wizard. 00:02:10.979 --> 00:02:15.641 So also it's about simplifying the workflow into multiple 00:02:15.660 --> 00:02:18.020 steps that make them digestible, just like this protein 00:02:18.020 --> 00:02:23.520 shake. And finally it, it gives you the opportunity 00:02:23.520 --> 00:02:26.740 to provide more explanation for what each form does, 00:02:26.740 --> 00:02:29.570 by being able to fit more information when you 00:02:29.570 --> 00:02:31.950 break it up across multiple pages, like what they 00:02:31.960 --> 00:02:33.970 do with TurboTax. 00:02:33.970 --> 00:02:39.060 Who here has filed their taxes? 00:02:39.060 --> 00:02:42.510 Yeah. I did not. I just did this so 00:02:42.510 --> 00:02:47.090 I see who raised his hand. 00:02:47.090 --> 00:02:53.700 OK. So I had a, a software architecture gig 00:02:53.740 --> 00:02:56.900 at EarlyShare about a couple of years ago where 00:02:56.900 --> 00:03:00.880 I helped them launch their site. EarlyShare is kind 00:03:00.880 --> 00:03:04.520 of like KickStarter or Indiegogo, except it's focused on 00:03:04.520 --> 00:03:09.290 allowing people to do crowd investment in businesses. 00:03:09.300 --> 00:03:11.650 And it was a website that was being built 00:03:11.650 --> 00:03:13.960 fast in order to catch up with some legal 00:03:13.960 --> 00:03:19.770 laws in the U.S. that would allow crowd investment. 00:03:19.780 --> 00:03:24.020 So I helped them launch the site and they 00:03:24.020 --> 00:03:29.000 had, they, as part of their website, they needed 00:03:29.000 --> 00:03:32.800 a couple of onboarding wizards. One for investors and 00:03:32.800 --> 00:03:36.290 one for business people. 00:03:36.290 --> 00:03:38.579 But there were other requirements. Like, the business was 00:03:38.580 --> 00:03:43.541 bootstrapped. We were only two developers. Me as the 00:03:43.541 --> 00:03:45.820 senior and then there was a junior with a 00:03:45.820 --> 00:03:49.240 CTO and a designer and that's it. He wanted 00:03:49.240 --> 00:03:51.329 us to move super fast, and I was brought 00:03:51.329 --> 00:03:54.591 in as the Rails expert. 00:03:54.600 --> 00:03:56.560 So I had not written a wizard in like 00:03:56.580 --> 00:03:59.140 four years before that. Or maybe five years. Like, 00:03:59.140 --> 00:04:02.170 maybe since the days I did Java development. And 00:04:02.170 --> 00:04:04.580 when I started tackling this problem in Ruby, you 00:04:04.580 --> 00:04:05.960 know, I like, I went online, checked some Google 00:04:05.960 --> 00:04:11.030 guides and all that or StackOverflow, whatever. 00:04:11.030 --> 00:04:15.689 And none of their approaches satisfied me. So let's 00:04:15.689 --> 00:04:17.959 talk about what I found. 00:04:17.980 --> 00:04:20.551 So the wizard example, though, is basically, you have 00:04:20.560 --> 00:04:23.629 four steps. Step one is collect basic info. Step 00:04:23.629 --> 00:04:26.641 two is details, more details. Step three is upload 00:04:26.641 --> 00:04:29.640 some document content. Step four is just preview before 00:04:29.640 --> 00:04:32.409 you finish the wizard. And then once it's done, 00:04:32.409 --> 00:04:34.870 it shows you a summary, like a landing page 00:04:34.870 --> 00:04:38.401 for the project that, that the business is proposing 00:04:38.420 --> 00:04:40.420 for investment. 00:04:40.420 --> 00:04:46.700 OK. So, I mean, the goals I had was 00:04:46.700 --> 00:04:49.029 the Rails server had to persist every progress on 00:04:49.029 --> 00:04:53.251 every step. So no, like, js client-side tricks. That 00:04:53.260 --> 00:04:56.851 was out of scope. I wanted it to still, 00:04:56.860 --> 00:05:00.869 like, be RESTful, like, which is a common issue 00:05:00.869 --> 00:05:03.200 with wizard, like, building wizards. How to make them 00:05:03.200 --> 00:05:05.080 properly RESTful. 00:05:05.080 --> 00:05:09.460 I wanted to also stick with MVC, object-oriented principles 00:05:09.460 --> 00:05:11.841 because we're using an object-oriented language. So I wanted 00:05:11.860 --> 00:05:13.599 to make sure that the code is maintainable by 00:05:13.600 --> 00:05:18.200 other developers going to the feature. 00:05:18.200 --> 00:05:22.151 And then some non-functional requirements, like productivity. So that 00:05:22.151 --> 00:05:26.749 was part of the concern that the CTO had, 00:05:26.749 --> 00:05:27.890 which is he wanted us to move fast, like, 00:05:27.900 --> 00:05:30.500 really, really fast. That was part of the reason 00:05:30.500 --> 00:05:32.291 why he brought me in. Well, big mistake. I, 00:05:32.300 --> 00:05:36.330 I pay attention to details and nice design concerns. 00:05:36.330 --> 00:05:38.409 So I will slow him down but for good 00:05:38.409 --> 00:05:38.740 reasons. 00:05:38.740 --> 00:05:41.050 I'll slow him down and then he'll go much 00:05:41.050 --> 00:05:44.060 faster later on. 00:05:44.060 --> 00:05:48.840 Still, the story does have a happy ending. So 00:05:48.840 --> 00:05:53.521 maintainability, by both junior and senior developers. They had 00:05:53.521 --> 00:05:57.069 one senior developer in Brazil as well. Which I 00:05:57.080 --> 00:05:59.760 just remembered. He was brought in a little later 00:05:59.760 --> 00:06:01.520 on. 00:06:01.540 --> 00:06:04.310 Performance concerns. Security concerns. 00:06:04.310 --> 00:06:06.990 So it's pretty, it's pretty basic stuff. Like, I 00:06:06.990 --> 00:06:08.920 mean, these are the concerns that we should care 00:06:08.920 --> 00:06:13.320 about whenever we build any feature, really. 00:06:13.320 --> 00:06:16.540 So one approach that I've seen on actual code 00:06:16.540 --> 00:06:18.380 bases, I actually saw it on a code base 00:06:18.380 --> 00:06:21.270 that I maintained on a following project after that 00:06:21.270 --> 00:06:26.920 one, was one controller per wizard step. 00:06:26.920 --> 00:06:31.190 So you create a REST resource per wizard step. 00:06:31.200 --> 00:06:36.990 And you had multiple controllers, multiple sets of views 00:06:37.000 --> 00:06:39.130 and helpers. And then each controller redirects to the 00:06:39.140 --> 00:06:41.630 next one. So something like this. And you could 00:06:41.630 --> 00:06:44.680 do it either with one ActiveRecord that has conditional 00:06:44.680 --> 00:06:46.281 validations for each step, where it says OK, if 00:06:46.281 --> 00:06:49.679 step one, validate presence of name, if step two, 00:06:49.680 --> 00:06:52.501 validate presence of blah, blah, blah. Or you could 00:06:52.501 --> 00:06:53.750 have multiple ActiveRecords. 00:06:53.750 --> 00:07:01.850 But either way, who here could find concerns with 00:07:01.850 --> 00:07:03.831 this approach, or at least something that could be 00:07:03.840 --> 00:07:07.468 improved on? Somebody volunteer? Go ahead. 00:07:07.468 --> 00:07:09.590 AUDIENCE: [indecipherable - 00:07:10] 00:07:09.590 --> 00:07:13.660 A.M.: And what's the concern with that? So what 00:07:13.660 --> 00:07:18.420 if you have a whole bunch of controllers? 00:07:18.420 --> 00:07:21.360 AUDIENCE: [indecipherable - 00:07:16] 00:07:21.780 --> 00:07:26.030 A.M.: OK. I mean, I've built applications that managed 00:07:27.340 --> 00:07:34.340 user profiles, user accounts, blog posts, for example, whatever. 00:07:35.300 --> 00:07:36.651 You need a controller for each one of those. 00:07:36.651 --> 00:07:38.439 I don't think you could escape that. 00:07:38.440 --> 00:07:40.890 So I'm gonna give other people a chance to 00:07:40.890 --> 00:07:42.601 talk, but I do get your point. I want 00:07:42.601 --> 00:07:43.649 to clarify it. 00:07:43.649 --> 00:07:44.441 Go ahead. 00:07:44.441 --> 00:07:46.849 AUDIENCE: I was gonna say repetition- 00:07:46.849 --> 00:07:47.640 A.M.: Exactly. 00:07:47.640 --> 00:07:49.241 AUDIENCE: Re-usability and dependencies. 00:07:49.241 --> 00:07:51.830 A.M.: Yeah. So quite a bit of that code 00:07:51.830 --> 00:07:53.790 is repetitive. It was just, it was always loading 00:07:53.800 --> 00:07:58.059 the resource. It's almost the same resource. Actually, if 00:07:58.060 --> 00:07:59.900 you use one ActiveRecord, it is the same resource. 00:07:59.900 --> 00:08:03.070 And then we'd run some validations and then it 00:08:03.070 --> 00:08:05.110 would pass to the next controller. So, I mean, 00:08:05.140 --> 00:08:07.000 there was quite a bit of repetition. 00:08:07.000 --> 00:08:11.170 We try to add features a couple of months 00:08:11.170 --> 00:08:14.170 after the, after a developer had built that wizard 00:08:14.170 --> 00:08:18.040 on that project, and they wanted us to deliver 00:08:18.040 --> 00:08:24.090 something in a week, and apparently another developer, before 00:08:24.120 --> 00:08:26.400 I joined that team, had tried to implement that 00:08:26.400 --> 00:08:27.790 feature and it took him a month. And he 00:08:27.790 --> 00:08:30.440 still couldn't do it with the, with the design 00:08:30.440 --> 00:08:30.940 they had. 00:08:30.940 --> 00:08:32.640 It was still, it was just taking a long 00:08:32.640 --> 00:08:34.510 time. Like, he was still not done. And then 00:08:34.520 --> 00:08:39.309 that guy left. So I ended up solving the 00:08:39.309 --> 00:08:41.760 problem with another senior guy. And it was, so, 00:08:41.760 --> 00:08:44.208 I ended up applying this ultra light maintainable wizard 00:08:44.208 --> 00:08:47.601 approach that I discovered on the EarlyShares dot com 00:08:47.601 --> 00:08:51.240 project, and it worked out really well. So, which, 00:08:51.240 --> 00:08:53.920 I'll talk about a little later. But that helped 00:08:53.920 --> 00:08:57.510 us actually develop it in, if I remember right, 00:08:57.510 --> 00:09:01.540 it was about seven days. 00:09:01.540 --> 00:09:07.050 Test first, and rewriting the entire thing, also. 00:09:07.060 --> 00:09:08.610 But it was specifically because we didn't have that 00:09:08.620 --> 00:09:11.450 many controllers anymore. So, we wrote a lot less 00:09:11.460 --> 00:09:12.660 tests so we had a lot less code to 00:09:12.660 --> 00:09:15.080 maintain. So that was part of it. 00:09:15.080 --> 00:09:17.400 So, another approach I've seen is one controller. Sorry. 00:09:17.400 --> 00:09:20.930 Oh, OK, that's just the critique. We already went 00:09:20.930 --> 00:09:22.080 over that. I don't think I want to go 00:09:22.080 --> 00:09:24.840 too much into details for that cause we're limited 00:09:24.840 --> 00:09:25.480 on time. 00:09:25.480 --> 00:09:28.240 But yeah, let's go next to one action and 00:09:28.240 --> 00:09:30.510 presenter per wizard step. So, I mean, another approach 00:09:30.510 --> 00:09:33.340 is, OK, keep one ActiveRecord, but I've also seen 00:09:33.340 --> 00:09:38.390 this approach in a code base, where there were 00:09:38.390 --> 00:09:43.900 different, say, new_step1, create_step1, new_step2, create_step2. So there were 00:09:43.920 --> 00:09:46.860 just, like, eight actions on that controller, each mimicking 00:09:46.860 --> 00:09:50.690 the new and, and, and create, say, on the 00:09:50.700 --> 00:09:51.880 RESTful resource. 00:09:51.880 --> 00:09:55.860 So, although it feels RESTful, it was not REST 00:09:55.860 --> 00:10:00.690 anymore. It already broke out of the REST paradigm. 00:10:00.690 --> 00:10:03.350 So we can improve over that. 00:10:03.350 --> 00:10:07.240 Also, it still had some repetitive code across the 00:10:07.240 --> 00:10:09.830 actions. So, I mean, it was, it was just 00:10:09.840 --> 00:10:14.060 a slight improvement to the problem. Not much. 00:10:14.060 --> 00:10:17.820 Using presenters, which is an abstraction layer between the 00:10:17.820 --> 00:10:20.930 ActiveRecord and the controller is an improvement in the 00:10:20.930 --> 00:10:22.800 sense that you can put the validations for each 00:10:22.800 --> 00:10:28.060 presenter per step separately and not have conditional validations. 00:10:28.060 --> 00:10:32.240 I'll talk more about that going forward. 00:10:32.240 --> 00:10:35.090 So it was more something like this, where the 00:10:35.100 --> 00:10:38.670 controller had a whole bunch of actions that are 00:10:38.670 --> 00:10:43.690 connecting to presenters that are talking to an ActiveRecord. 00:10:44.480 --> 00:10:45.520 OK. 00:10:47.500 --> 00:10:52.450 So I already went over the caveats of that. 00:10:52.450 --> 00:10:56.210 OK. Who here has written a wizard with session 00:10:56.280 --> 00:11:00.840 accumulation approach? How, how did that work out for 00:11:00.840 --> 00:11:02.240 you or, do you think- 00:11:02.240 --> 00:11:03.920 AUDIENCE: That's why I'm here. 00:11:03.960 --> 00:11:06.940 -well, I'm sorry if it sounds. Well, tell me 00:11:07.000 --> 00:11:07.750 why you're here. I'm curious. 00:11:07.840 --> 00:11:08.420 AUDIENCE: Well, I mean, right now it's just that 00:11:08.420 --> 00:11:12.330 it's to the point where we're breaking it down 00:11:12.330 --> 00:11:18.320 further, it was a very basic general implementation. And 00:11:18.340 --> 00:11:22.480 now dealing with the fact that we have so 00:11:22.480 --> 00:11:26.160 much session iteration that I have to pass it 00:11:26.160 --> 00:11:26.730 between, you know, controllers. We deal with it from 00:11:26.730 --> 00:11:27.300 multiple angles, and it's, I mean, I can't put 00:11:27.300 --> 00:11:28.490 that stuff in a model. So my controllers are 00:11:28.490 --> 00:11:29.120 getting really out of hand. 00:11:29.120 --> 00:11:29.900 A.M.: Exactly. Yeah. Yup. Yup. Yup. 00:11:29.920 --> 00:11:31.220 So you end up with the live session management 00:11:31.220 --> 00:11:33.600 code in the controller, which breaks MVC. So if 00:11:33.600 --> 00:11:35.910 you're not breaking REST, you break MVC. It's really 00:11:35.910 --> 00:11:38.400 tough. It's a tough problem. 00:11:38.400 --> 00:11:40.930 AUDIENCE: Can you explain what session accumulation is? 00:11:40.940 --> 00:11:42.820 A.M.: Yes. So, actually, maybe I should have somebody 00:11:42.820 --> 00:11:45.310 explain that. I saw you raise your hand. Would 00:11:45.310 --> 00:11:47.820 you mind explaining it to the audience. 00:11:47.820 --> 00:11:53.150 AUDIENCE: Sure. It's basically, as you're going through the 00:11:53.150 --> 00:11:58.450 specs, that you're storing all of the information that 00:11:58.460 --> 00:12:01.500 needs to be in the session. So then, you 00:12:01.500 --> 00:12:03.240 go through step 00:12:03.240 --> 00:12:06.460 one. You gather the basic info from the form. 00:12:06.460 --> 00:12:08.880 When submitting the form, instead of storing that in 00:12:08.880 --> 00:12:11.250 an ActiveRecord, you actually store it in, in the 00:12:11.250 --> 00:12:15.520 session, using the session helper in the, in the 00:12:15.540 --> 00:12:17.970 Rails controller. And then once you move to, and 00:12:17.980 --> 00:12:19.730 then you redirect to step two, and then you 00:12:19.740 --> 00:12:21.790 submit that form again, and then you add more 00:12:21.790 --> 00:12:23.210 stuff to the session. 00:12:23.210 --> 00:12:25.470 Once you reach the last step, kind of like 00:12:25.470 --> 00:12:27.930 what you see in this diagram, that's when you're 00:12:27.940 --> 00:12:30.330 ready to create the ActiveRecord. So you pass all 00:12:30.330 --> 00:12:34.320 of this as the params and the ActiveRecord will 00:12:34.320 --> 00:12:41.320 validate it and then you're done. 00:12:41.440 --> 00:12:48.440 OK. So, so I mean as far as critique. 00:12:49.480 --> 00:12:52.900 So reliance of session, storing objects in the session 00:12:52.940 --> 00:12:55.980 has implications on scalability. Usually you want to store 00:12:56.000 --> 00:13:00.020 ids of primitives because they're easier to move across 00:13:00.080 --> 00:13:02.500 servers when it's primitive data and be able to 00:13:02.500 --> 00:13:04.290 support multiple servers. 00:13:04.300 --> 00:13:07.220 My understanding is if you have actual objects in 00:13:07.220 --> 00:13:10.270 the session, it makes it harder for you to 00:13:10.280 --> 00:13:11.930 scale. 00:13:11.960 --> 00:13:14.870 Controller code is more complex because of managing session 00:13:14.870 --> 00:13:18.330 data. Validations could get defined twice, because you might 00:13:18.380 --> 00:13:20.190 have to validate on every step as well, in 00:13:20.220 --> 00:13:23.000 JavaScript or in a, in a presenter or something. 00:13:23.000 --> 00:13:25.630 And, also present at the last step in the 00:13:25.630 --> 00:13:26.100 model. 00:13:26.100 --> 00:13:28.200 So again, I mean, if you're not breaking REST, 00:13:28.200 --> 00:13:29.820 you're breaking MVC. If you're not breaking MVC, you're 00:13:29.820 --> 00:13:34.670 breaking duplication whatever, concerns, so, it's a tough problem. 00:13:34.670 --> 00:13:38.710 Hidden value accumulation. Somebody share with us what this 00:13:38.740 --> 00:13:41.570 is, or, it's very similar to session accumulation. 00:13:41.570 --> 00:13:42.720 Yeah, go ahead. 00:13:42.720 --> 00:13:46.210 AUDIENCE: Really, when you're submitting the form at each 00:13:46.210 --> 00:13:49.680 step you're shoving all the values from the form 00:13:49.680 --> 00:13:53.170 into hidden fields on the page, and then eventually, 00:13:53.170 --> 00:13:57.460 when you hit submit, the final version will just 00:13:57.460 --> 00:14:00.260 set everything to the server. 00:14:00.260 --> 00:14:01.390 A.M.: Yup. 00:14:01.400 --> 00:14:04.900 So it's not stateful, it's stateless, because it keeps, 00:14:04.900 --> 00:14:07.600 like, each request has its state. You don't have 00:14:07.600 --> 00:14:11.110 to maintain the state in a session. So the 00:14:11.110 --> 00:14:14.970 performance implications are gone. Like, it has no problems 00:14:14.980 --> 00:14:18.860 in scalability. 00:14:18.860 --> 00:14:21.740 But you might, you, you might not want to 00:14:21.740 --> 00:14:23.400 expose the values all the time on the, on 00:14:23.400 --> 00:14:25.440 the user page. You can hash them or do 00:14:25.440 --> 00:14:29.090 encoding on them, so that could improve that, that 00:14:29.090 --> 00:14:32.540 problem with regards to keeping form data in a, 00:14:32.540 --> 00:14:34.100 in hidden fields on the page every step of 00:14:34.100 --> 00:14:36.690 the way. 00:14:36.690 --> 00:14:43.530 But there's, yeah, I mean, but the complexity is 00:14:43.540 --> 00:14:45.690 still there, with having to manage the accumulation and 00:14:45.700 --> 00:14:48.380 having to construct the model at the end. 00:14:48.380 --> 00:14:49.580 So it's a slight improvement. 00:14:49.580 --> 00:14:52.050 Who here has used the state matching for a 00:14:52.060 --> 00:14:53.140 wizard? 00:14:53.140 --> 00:14:58.080 OK. Do you mind sharing with us your experience 00:14:58.080 --> 00:14:58.720 with it? 00:14:58.720 --> 00:15:02.450 AUDIENCE: I think main problem that you run into 00:15:02.450 --> 00:15:06.180 is that you get fat models, cause you have 00:15:06.200 --> 00:15:07.390 to put all of the different validations into different 00:15:07.390 --> 00:15:09.310 states. But overall, I found that it was a 00:15:09.310 --> 00:15:12.500 better compromise than the other options. 00:15:12.500 --> 00:15:15.650 A.M.: Generally it is. One, yeah. So, you create 00:15:15.650 --> 00:15:20.530 one ActiveRecord. You make the ActiveRecord a state machine. 00:15:20.540 --> 00:15:23.350 You have to add a step column on that 00:15:23.350 --> 00:15:27.070 model to support which step you're on when it, 00:15:27.080 --> 00:15:29.250 in order for the validation to know which validations 00:15:29.260 --> 00:15:31.330 to run for what step. So that way you 00:15:31.330 --> 00:15:33.750 say, OK, on step one, if you have that 00:15:33.750 --> 00:15:35.630 column, you'll say, OK, you'll have validations that say, 00:15:35.640 --> 00:15:38.600 OK, if it's step one, then I'm gonna check 00:15:38.600 --> 00:15:40.840 for first name and last name presence. If it's 00:15:40.840 --> 00:15:41.990 step two I'm gonna, I'm gonna check that the 00:15:42.000 --> 00:15:44.370 project details are present. And so on and so 00:15:44.370 --> 00:15:48.730 forth, depending on what each form, what field, what 00:15:48.730 --> 00:15:51.360 field each form contains on the, in the specific 00:15:51.380 --> 00:15:53.840 step. 00:15:53.840 --> 00:16:00.840 So yeah, different view per step. I already went 00:16:01.820 --> 00:16:03.051 over conditional validations. 00:16:03.060 --> 00:16:05.420 To share an example, it looks something like that, 00:16:05.440 --> 00:16:12.440 like validate :phone, presence: true, if current_step is shipping. 00:16:12.680 --> 00:16:14.000 So that's just one way of doing it. There's 00:16:14.000 --> 00:16:15.870 other better ways of doing it. There's also gems 00:16:15.870 --> 00:16:17.020 out there that help you with that. But that's 00:16:17.020 --> 00:16:18.280 one way of doing it. 00:16:18.280 --> 00:16:20.960 AUDIENCE: ActiveRecord has the ability to run conditional validations 00:16:20.960 --> 00:16:22.430 like that. You don't have to run a block. 00:16:22.430 --> 00:16:26.640 A.M.: Mhmm. Yup. Yup. I'm familiar with that. Yeah, 00:16:26.640 --> 00:16:28.090 that's why I mentioned, there's multiple ways of doing 00:16:28.090 --> 00:16:29.720 that. That's just one example. 00:16:29.720 --> 00:16:32.340 AUDIENCE: How does, how is the state machine different 00:16:32.340 --> 00:16:39.340 than the first, better than any of the ones 00:16:40.140 --> 00:16:43.580 you mentioned, [indecipherable - 00:16:39] 00:16:44.440 --> 00:16:46.780 A.M.: OK. With the other one, you could cheat 00:16:46.780 --> 00:16:50.130 a bit and set an in memory variable that 00:16:50.130 --> 00:16:52.100 represents the step name that you're on and then 00:16:52.100 --> 00:16:55.190 do that conditional validation that way, whereas with this 00:16:55.190 --> 00:16:58.030 one, you have, you're only working with one model 00:16:58.030 --> 00:17:02.210 and you don't, you haven't managed the stepping. So 00:17:02.220 --> 00:17:03.750 yeah, with the other approach, the controller is doing 00:17:03.750 --> 00:17:06.009 management of the stepping. In this one the model 00:17:06.009 --> 00:17:09.191 is doing the management of the stepping. 00:17:09.200 --> 00:17:13.869 So critique. Well, first of all, it puts in 00:17:13.880 --> 00:17:15.799 presentation concerns, like adding an extra column to our 00:17:15.800 --> 00:17:20.069 presenter's state, sorry, step, is not part of the 00:17:20.069 --> 00:17:23.810 domain, the business domain. So when you're doing MVC, 00:17:23.819 --> 00:17:25.910 usually the model, you're trying to put in it 00:17:25.910 --> 00:17:29.970 as much decoupled logic that's focused on the business 00:17:29.980 --> 00:17:32.660 at hand as possible in order to maintain that 00:17:32.680 --> 00:17:35.870 separately from any view concerns or controller concerns. 00:17:35.870 --> 00:17:39.071 I mean, you can put anything in the model, 00:17:39.080 --> 00:17:41.369 really. But the reason why we do that is, 00:17:41.369 --> 00:17:43.790 in my experience, when I'm maintaining a code base, 00:17:43.790 --> 00:17:47.171 if I'm not having to manage view concerns like 00:17:47.180 --> 00:17:49.950 stepping into a state machine and a model concern, 00:17:49.950 --> 00:17:53.999 like the business rules of, of what happens when, 00:17:54.000 --> 00:17:56.980 you know, like the project description is not present 00:17:56.980 --> 00:17:59.610 or whatever, then it's easier for me to maintain 00:17:59.620 --> 00:18:01.640 that model, cause I'm not thinking on one thing 00:18:01.640 --> 00:18:03.441 at a time. I'm not thinking multiple things at 00:18:03.441 --> 00:18:05.299 the same time. 00:18:05.300 --> 00:18:10.481 Also, it makes those models smaller files, if you 00:18:10.481 --> 00:18:12.940 separate those concerns. You don't want a huge model 00:18:12.940 --> 00:18:15.869 as maintaining a state machine and maintaining business rules 00:18:15.869 --> 00:18:18.510 and maintaining like ten other things. You could manage 00:18:18.510 --> 00:18:23.360 that with splitting that into modules or concerns, but 00:18:23.380 --> 00:18:26.821 still, when I'm working with that model, my head 00:18:26.821 --> 00:18:28.779 will have the context of everything at once. SO 00:18:28.780 --> 00:18:31.581 it wouldn't, like, this is more of an advanced 00:18:31.581 --> 00:18:33.869 programming thing. Like, once you've been programming for three 00:18:33.869 --> 00:18:36.932 years at least, you'll, you'll start noticing that. 00:18:36.940 --> 00:18:42.728 You'll start noticing the subtleties with regards to mixing 00:18:42.728 --> 00:18:46.071 concerns. Like, you start understanding why people say follow 00:18:46.080 --> 00:18:49.369 the single responsibility principle. I'm not a fan of 00:18:49.369 --> 00:18:51.860 following it dogmatically, I, but I think it's a 00:18:51.860 --> 00:18:54.061 good guideline, like any other guideline, where if you 00:18:54.061 --> 00:18:57.499 could minimize responsibilities in a model and have it 00:18:57.500 --> 00:19:01.400 not manage view concerns, then do that. Especially if 00:19:01.400 --> 00:19:03.630 MVC prescribes that as well as that's what all 00:19:03.660 --> 00:19:06.071 Rails developers on the field would expect. 00:19:06.080 --> 00:19:12.148 So I think I pretty much sold that. So 00:19:12.148 --> 00:19:15.040 yeah, so I mean, I think that makes it 00:19:15.040 --> 00:19:19.280 pretty clear why I don't like this approach that 00:19:19.280 --> 00:19:19.821 much. 00:19:19.821 --> 00:19:22.559 Also, it's a bit techy. Like, thinking of the 00:19:22.560 --> 00:19:24.540 wizard as a state machine is a bit computer 00:19:24.540 --> 00:19:27.250 science-y. Like, I mean, I have a background in 00:19:27.250 --> 00:19:29.650 computer science, but, the, the point of anything you 00:19:29.650 --> 00:19:31.071 learn is to apply it in the right place 00:19:31.080 --> 00:19:33.700 for it, and I don't feel like, when I'm 00:19:33.700 --> 00:19:35.590 thinking about a wizard I'm thinking about the business 00:19:35.600 --> 00:19:36.789 problem. That's what I really want to think about. 00:19:36.789 --> 00:19:38.130 I don't want to think about a state machine. 00:19:38.130 --> 00:19:40.341 As cool as that is, that's not the time 00:19:40.341 --> 00:19:41.289 to think about it. 00:19:41.289 --> 00:19:45.691 So I mean, a thousand and one approaches is, 00:19:45.700 --> 00:19:48.009 there's a whole bunch of gems out there. Most 00:19:48.009 --> 00:19:50.250 of them will simplify the things I mentioned, or 00:19:50.280 --> 00:19:53.441 give you better, shorter DSLs for doing the approaches 00:19:53.441 --> 00:19:56.590 I mentioned. But none of them achieve all the 00:19:56.590 --> 00:19:58.899 goals at once, of having MVC, REST, and all 00:19:58.900 --> 00:19:59.640 of that. 00:19:59.640 --> 00:20:03.110 I mean, to get back to that, there's REST, 00:20:03.110 --> 00:20:06.290 MVC, OO, and then the non-functional requirements. So, let's 00:20:06.290 --> 00:20:09.701 go to, jump into this. I think we have 00:20:09.701 --> 00:20:14.290 about ten minutes left. 00:20:14.300 --> 00:20:17.590 So the first thing that, so I, I'm like, 00:20:17.590 --> 00:20:19.859 OK, let's try to solve this wizard problem from 00:20:19.860 --> 00:20:22.380 scratch, like, as if I just, I'm just gonna, 00:20:22.380 --> 00:20:25.250 like, get my tools out there. Like, the object-oriented 00:20:25.260 --> 00:20:30.640 principles, the domain-driven design principles. Who, who here has 00:20:30.640 --> 00:20:33.801 read the book Domain Driven Design? Or heard of 00:20:33.801 --> 00:20:36.200 it, at least? 00:20:36.200 --> 00:20:38.349 It's a book that I, my team did a 00:20:38.349 --> 00:20:41.340 book club on, or a previous team, like six 00:20:41.340 --> 00:20:43.870 years ago, did a book club on for the 00:20:43.880 --> 00:20:47.831 sake of learning how to do object-oriented design on 00:20:47.840 --> 00:20:49.879 real business problems. Cause a lot of the time 00:20:49.880 --> 00:20:51.900 you learn object orientation, but it's hard to figure 00:20:51.900 --> 00:20:54.191 out how to create the right objects for the 00:20:54.200 --> 00:20:56.480 real, for the right person's problem. It's, that, that 00:20:56.480 --> 00:20:58.119 book is a very good book on how to 00:20:58.120 --> 00:20:58.920 tackle that. 00:20:58.940 --> 00:21:00.879 So I, I started using those tools. Like, whatever 00:21:00.880 --> 00:21:02.400 I learned from that book, whatever I learned from 00:21:02.400 --> 00:21:07.770 object-oriented programming. Whatever I learned from, like REST. To 00:21:07.780 --> 00:21:11.280 try to figure out what a wizard is. 00:21:11.280 --> 00:21:14.130 Before I go ahead and talk more of what 00:21:14.130 --> 00:21:16.990 a wizard is, what do you think a wizard, 00:21:17.000 --> 00:21:19.100 the wizard's highest goal is? 00:21:19.100 --> 00:21:20.630 Go ahead. 00:21:20.630 --> 00:21:25.051 AUDIENCE: To serve views for the user. 00:21:25.060 --> 00:21:28.349 A.M.: That's correct. So, you stumped me. Cause I 00:21:28.349 --> 00:21:30.291 was gonna ask about the highest goal from the 00:21:30.300 --> 00:21:31.769 developer's point of view, but you're right, we should 00:21:31.769 --> 00:21:33.730 think about the user's perspective first. 00:21:33.740 --> 00:21:38.091 Now, let's dig, let's dig a little. No, that's 00:21:38.100 --> 00:21:40.830 good. Let's dig a level lower. So, OK, so 00:21:40.830 --> 00:21:43.580 we know that. That's our guiding principle, is OK, 00:21:43.580 --> 00:21:45.149 to serve to make things easier for the user. 00:21:45.149 --> 00:21:50.280 But, next, what, why, why, OK, technically what, what 00:21:50.280 --> 00:21:51.120 is a wizard doing? 00:21:51.140 --> 00:21:52.790 OK, that's my next question. What is a wizard 00:21:52.790 --> 00:21:54.160 really doing? Go ahead. 00:21:54.160 --> 00:21:57.470 AUDIENCE: Collect the proper set of validated values. 00:21:57.470 --> 00:22:00.770 A.M.: That's part of the work. What else? 00:22:00.770 --> 00:22:01.890 AUDIENCE: Break down the form so they're just small 00:22:01.890 --> 00:22:02.230 steps. 00:22:02.320 --> 00:22:04.440 A.M.: OK. Break down the data. Yup. Like separate 00:22:04.520 --> 00:22:05.920 it. What else? 00:22:05.920 --> 00:22:06.960 AUDIENCE: I was gonna say something really similar to 00:22:07.120 --> 00:22:09.040 that. Organize the data into, like, you know, making 00:22:09.040 --> 00:22:13.220 it weighted or in comprehensible sections. 00:22:14.020 --> 00:22:16.380 A.M.: OK. And what's the end goal of running 00:22:16.420 --> 00:22:18.880 through the entire wizard? 00:22:18.920 --> 00:22:21.391 AUDIENCE: Creating an object. 00:22:21.391 --> 00:22:24.758 A.M.: Yup. Pretty much. So a wizard is nothing 00:22:24.780 --> 00:22:29.220 but the good old builder design pattern. Anybody's heard 00:22:29.220 --> 00:22:30.821 of it. I mean, I used to be a 00:22:30.821 --> 00:22:33.269 hardcore Java geek and design patterns were big in- 00:22:33.269 --> 00:22:35.761 [audio jump] seven days - in Ruby. 00:22:35.761 --> 00:22:38.720 But it's still good to know about things like 00:22:38.720 --> 00:22:40.980 that, cause that pattern flashed in my head right 00:22:40.980 --> 00:22:42.520 away. I'm like, oh wow, a wizard is nothing 00:22:42.540 --> 00:22:44.831 but a builder. Like, it, all it does is 00:22:44.831 --> 00:22:47.409 like an assembly line of building a car, where 00:22:47.409 --> 00:22:50.370 step one, you know, whatever, you put the chassis, 00:22:50.380 --> 00:22:53.091 second, like, step two is you add more, I 00:22:53.100 --> 00:22:54.649 don't know, you add the doors. Step three, you 00:22:54.649 --> 00:22:57.061 add the windows. Four, five, and then all of 00:22:57.061 --> 00:23:01.629 the sudden you've built a car. So that's really 00:23:01.629 --> 00:23:06.681 what it is. 00:23:06.681 --> 00:23:11.039 Second part of the philosophy that I was following 00:23:11.040 --> 00:23:14.301 is, each step in a wizard is nothing but 00:23:14.301 --> 00:23:16.570 a partial view of that main, full object you're 00:23:16.570 --> 00:23:19.459 building. So, one, one step is about, say I'm 00:23:19.460 --> 00:23:21.030 ordering a car and I want to customize that 00:23:21.060 --> 00:23:22.990 car. Like, one step will show me the exterior 00:23:22.990 --> 00:23:25.770 body and another will show me the interior to 00:23:25.770 --> 00:23:29.941 customize the interior with, whatever, leather or mahogany front-panel, 00:23:29.941 --> 00:23:32.330 whatever. And then, and then a third part lets 00:23:32.330 --> 00:23:33.410 me customize the engine. 00:23:33.410 --> 00:23:35.719 So it's just, so all what steps are, are 00:23:35.740 --> 00:23:38.931 views. Like, instead of thinking about them as states 00:23:38.940 --> 00:23:41.330 and in a state machine, this is a more 00:23:41.340 --> 00:23:43.470 higher level way of thinking about it. It's less 00:23:43.470 --> 00:23:46.919 technical and more, it's just, I'm viewing one part 00:23:46.920 --> 00:23:49.730 of a model. 00:23:49.740 --> 00:23:54.721 Third part is if you were to, so, with 00:23:54.721 --> 00:23:56.480 that in mind, if you ever think about the 00:23:56.480 --> 00:23:59.869 REST resources, it's very simple now. It's done. Like, 00:23:59.869 --> 00:24:02.091 you have the main model, that's the main resource. 00:24:02.100 --> 00:24:04.679 And then you have the model parts, nested model 00:24:04.680 --> 00:24:07.050 part, under the main model. That's the second resource. 00:24:07.050 --> 00:24:10.390 That's it. You have two RESTful resources. Very clean. 00:24:10.390 --> 00:24:12.640 So every time you're walking through the steps of 00:24:12.640 --> 00:24:17.040 a wizard, you're actually editing a model part. So, 00:24:17.040 --> 00:24:19.811 and, so that makes it very, very clear what 00:24:19.820 --> 00:24:22.499 the REST resource is. 00:24:22.500 --> 00:24:25.571 Another thing in my philosophy about it was I 00:24:25.580 --> 00:24:28.049 did not want to have conditional validations, cause they 00:24:28.049 --> 00:24:30.280 make a model hard to maintain. It's harder to 00:24:30.280 --> 00:24:31.910 read if statements. Like, if I can have those 00:24:31.910 --> 00:24:35.250 without if statements, it would be better. Especially when 00:24:35.250 --> 00:24:37.250 you come back to maintain that wizard six months 00:24:37.260 --> 00:24:39.801 later and then a year later and, on, on 00:24:39.801 --> 00:24:41.969 both projects I was on, they actually added steps 00:24:41.969 --> 00:24:43.630 to the wizard. So they started with four steps 00:24:43.640 --> 00:24:46.030 and then they grew to nine steps. 00:24:46.030 --> 00:24:51.120 And the more I can separate that stuff, the, 00:24:51.120 --> 00:24:55.571 the better. And then finally I just wanted to 00:24:55.580 --> 00:24:57.729 maintain the views in separate view files as well. 00:24:57.740 --> 00:25:00.100 I didn't want a single view file that would 00:25:00.100 --> 00:25:01.341 do it the way I used to write code 00:25:01.341 --> 00:25:03.759 in ASB where I'd have a crazy if-else statement 00:25:03.760 --> 00:25:06.081 that says if step1 show this part of the 00:25:06.081 --> 00:25:09.529 form, if step2, show me the project details, if 00:25:09.529 --> 00:25:12.840 step3, show me a document content upload. I don't 00:25:12.840 --> 00:25:19.840 want that. That's, yeah. That's ASP programming. 00:25:21.060 --> 00:25:28.060 AUDIENCE: If they change the order of the steps, 00:25:28.060 --> 00:25:31.440 you want the steps [indecipherable] step three became step 00:25:31.540 --> 00:25:32.660 four. 00:25:33.700 --> 00:25:35.340 A.M.: Yeah. It'll work. 00:25:36.840 --> 00:25:40.960 OK. So, so really I mean, high level is 00:25:41.040 --> 00:25:42.829 just, I have the main model. That's the main 00:25:42.829 --> 00:25:44.631 resource. And then the, on the, nested under it, 00:25:44.640 --> 00:25:49.130 there's the four different, so, what I end up 00:25:49.130 --> 00:25:52.400 doing is creating four different presenters. One per step. 00:25:52.400 --> 00:25:55.000 Which manages the validations for that step separately, as 00:25:55.000 --> 00:25:57.290 well as any stepping logic related to what happens 00:25:57.290 --> 00:25:58.681 when you land on that page. What are the 00:25:58.681 --> 00:26:01.159 defaults for that form? Should we initialize the phone 00:26:01.180 --> 00:26:03.540 number with zero, zero, zero, zeros, or should we, 00:26:03.540 --> 00:26:05.810 like, should, should we prefil the name from the 00:26:05.810 --> 00:26:08.630 logged in user account? These kinds of concerns now 00:26:08.630 --> 00:26:10.331 are uploaded cleanly to the model. 00:26:10.340 --> 00:26:12.700 So we're adhering to MVC. You handle all the 00:26:12.700 --> 00:26:15.800 wizard intelligence and business logic in the models now. 00:26:15.800 --> 00:26:17.769 You're not, or presenters. I mean, a presenter is 00:26:17.780 --> 00:26:19.941 just another form of a model that focuses on 00:26:19.941 --> 00:26:22.629 presented a vi- a part of a model. So, 00:26:22.629 --> 00:26:25.600 really, I'm, I'm using it in a loose sense. 00:26:25.600 --> 00:26:27.210 There's many ways to do presenters. I don't care 00:26:27.220 --> 00:26:28.280 which way. 00:26:28.280 --> 00:26:30.910 I do have a prescribed way here, but, the 00:26:30.910 --> 00:26:34.311 point of first to grasp is that you're operating 00:26:34.320 --> 00:26:36.029 on a part of the model. You're not operating 00:26:36.029 --> 00:26:37.500 on the full model. And you're doing the logic 00:26:37.500 --> 00:26:41.330 in the, in a model, not in a controller. 00:26:41.340 --> 00:26:43.071 And then the, the controller is the, yeah. So 00:26:43.080 --> 00:26:44.700 there's two of them. There's the one that manages 00:26:44.700 --> 00:26:46.919 the main model creation. So the first step of 00:26:46.920 --> 00:26:49.191 a wizard, when you create it, you create it 00:26:49.200 --> 00:26:51.710 with a main model controller. So if I have 00:26:51.710 --> 00:26:54.560 projects controller, I have a create action. And then 00:26:54.560 --> 00:26:58.119 that triggers the wizard. It'll, it'll create it and 00:26:58.120 --> 00:27:00.471 then redirects me to the first step. 00:27:00.480 --> 00:27:01.779 So when it redirects me to the first step 00:27:01.780 --> 00:27:03.981 it takes me to the edit page of model 00:27:03.981 --> 00:27:07.700 part, the nested model part, with id_step1, for example. 00:27:07.700 --> 00:27:10.779 Or id basic info. So you use the step 00:27:10.780 --> 00:27:13.101 names as the ids of that RESTful resource. Which 00:27:13.101 --> 00:27:20.019 is perfect REST. Like, that's, that, that goes with, 00:27:20.100 --> 00:27:21.690 that gives you an example of why, when people 00:27:21.690 --> 00:27:25.481 talk about REST outside of Rails, they tell you 00:27:25.481 --> 00:27:28.840 REST does not relate to having a database table. 00:27:28.840 --> 00:27:31.149 You can, so this, this, this is an example 00:27:31.149 --> 00:27:35.000 where the RESTful resource is a step that is 00:27:35.000 --> 00:27:37.670 a view of the model, but it's not a 00:27:37.670 --> 00:27:39.900 resource. It's not a database table. It's not a 00:27:39.900 --> 00:27:42.691 separate database table. It's just a virtual resource. 00:27:42.700 --> 00:27:44.499 I need to wrap it up and then I'll 00:27:44.500 --> 00:27:47.040 take, I'll take questions. So in a nutshell, you 00:27:47.040 --> 00:27:49.790 have the model resource, nested model. So you end 00:27:49.790 --> 00:27:54.200 up with URLs like that, which is very restful, 00:27:54.200 --> 00:27:58.800 again, cause, like, so you have projects, with the 00:27:58.800 --> 00:28:00.460 id. We were using friendly id on the projects, 00:28:00.460 --> 00:28:03.440 so the project says, yeah, so project1, then project_parts, 00:28:03.440 --> 00:28:05.540 and then the name of the step. And there'll 00:28:05.540 --> 00:28:07.700 be four steps for, you know, every time you 00:28:07.700 --> 00:28:09.279 run through that wizard. So there'll be four ids, 00:28:09.280 --> 00:28:11.860 only. It's a finite set. You don't have to 00:28:11.860 --> 00:28:13.520 store it in the database. 00:28:13.520 --> 00:28:20.140 So yeah, step names. There's id, contains validations, yeah. 00:28:20.200 --> 00:28:22.771 I already talked about all of that. So let's 00:28:22.771 --> 00:28:23.820 skip. 00:28:23.820 --> 00:28:26.469 So the routes is very, are very simple. You 00:28:26.469 --> 00:28:30.181 just have a resources projects. It's actually only create 00:28:30.181 --> 00:28:32.440 and show. I left the show out. There should 00:28:32.440 --> 00:28:34.659 be a show as well. Show is the landing 00:28:34.680 --> 00:28:37.300 page of the project when you finish the wizard. 00:28:37.300 --> 00:28:39.400 And then the project parts, which is edit and 00:28:39.400 --> 00:28:41.571 update. And it's that simple. 00:28:41.571 --> 00:28:44.289 So, so here's the project model. It's got the 00:28:44.289 --> 00:28:48.640 basic definition of that model. And associations and so 00:28:48.640 --> 00:28:51.421 on and so forth. However, what I end up 00:28:51.421 --> 00:28:54.070 doing is creating a presenter per wizard step, so, 00:28:54.070 --> 00:28:56.550 and I nest them under a directory that matches 00:28:56.580 --> 00:28:59.409 the model name, so, project, for example. And that's 00:28:59.409 --> 00:29:01.431 one way of doing it. There's many ways of 00:29:01.440 --> 00:29:03.299 doing it, but. 00:29:03.300 --> 00:29:06.230 In this case, only step one and two had 00:29:06.230 --> 00:29:08.841 customizations over that model. Step three did not have 00:29:08.841 --> 00:29:10.989 validations of its own, so I didn't even have 00:29:10.989 --> 00:29:14.520 to create a file for it. And step four 00:29:14.520 --> 00:29:16.340 actually didn't have anything either so I didn't have 00:29:16.340 --> 00:29:17.240 to create a file for it. 00:29:17.260 --> 00:29:20.480 But yeah. Step one, you can't see the details, 00:29:20.480 --> 00:29:22.930 but the point is that this is, these are 00:29:22.930 --> 00:29:27.000 validations for step one, only. So that's the first, 00:29:27.000 --> 00:29:29.220 and then the first step, as well as some 00:29:29.220 --> 00:29:33.170 business logic related to it, like initializing default, like 00:29:33.170 --> 00:29:37.620 initialize from user, which initializes from the signed in 00:29:37.620 --> 00:29:38.191 user. 00:29:38.200 --> 00:29:42.529 And then there's the project detail model, which has 00:29:42.540 --> 00:29:45.650 a few validations, only. Only three, cause it only 00:29:45.650 --> 00:29:49.280 has three fields on it. So that one is 00:29:49.280 --> 00:29:53.900 also, like, cleanly separated. Nice, easy to maintain. So 00:29:53.900 --> 00:29:57.331 you go back to maintain the code and it's 00:29:57.340 --> 00:29:58.679 like, it's like, it's squeaky clean. You know it's 00:29:58.680 --> 00:30:01.581 like so easy. It's like the way programming should 00:30:01.581 --> 00:30:06.039 be. 00:30:06.040 --> 00:30:08.140 So the project's controller, the create action, all it 00:30:08.140 --> 00:30:10.540 does is it creates the project and then redirects 00:30:10.540 --> 00:30:13.890 to the edit page of the first step, which 00:30:13.890 --> 00:30:18.780 is basic info. And then the project parts controller 00:30:18.780 --> 00:30:20.850 has the edit and the update and all it 00:30:20.850 --> 00:30:23.691 does is it steps through the wizard. Now, what 00:30:23.700 --> 00:30:25.430 I ended up doing here is the way I 00:30:25.430 --> 00:30:28.940 reasoned about it is that the project in MVC, 00:30:28.940 --> 00:30:32.039 or, sorry project controller in MVC is, or project 00:30:32.040 --> 00:30:36.071 parts controller, is actually, although it's a controller, it's 00:30:36.080 --> 00:30:38.239 a model of sorts. It's a model focused on 00:30:38.240 --> 00:30:39.470 control flow. 00:30:39.470 --> 00:30:41.571 And stepping through a wizard is control flow. So 00:30:41.580 --> 00:30:44.060 then I made the controller responsible for it. So 00:30:44.060 --> 00:30:47.599 the, so here, at the top, it, it defines 00:30:47.600 --> 00:30:49.120 the order of the steps, and then based on 00:30:49.120 --> 00:30:50.720 that it walks through them. So in a way 00:30:50.720 --> 00:30:53.480 the controller is the state machine, except I didn't 00:30:53.480 --> 00:30:56.681 need a state machine cause I'm not maintaining state. 00:30:56.681 --> 00:30:58.830 I do it with, I don't need to maintain 00:30:58.830 --> 00:31:00.450 state. Every time we finish a step we can 00:31:00.460 --> 00:31:02.479 redirect to the next step. And I can pass 00:31:02.480 --> 00:31:05.431 the id of the next step RESTfully and redirect 00:31:05.440 --> 00:31:06.609 to the next resource. 00:31:06.609 --> 00:31:08.500 So I, I don't need to maintain what step 00:31:08.500 --> 00:31:11.061 I'm at, on. It's always on each page. Like, 00:31:11.061 --> 00:31:12.659 on each page, I can know, if I'm on 00:31:12.660 --> 00:31:15.110 step two, I know that if I hit submit 00:31:15.110 --> 00:31:17.270 it'll take me to step three next. I don't 00:31:17.270 --> 00:31:19.330 have to, like I just know that from this 00:31:19.340 --> 00:31:23.931 array that we define over here, which orders the 00:31:23.940 --> 00:31:25.759 steps in the wizard. 00:31:25.760 --> 00:31:29.050 So, yeah, we're almost done. But yeah. I mean, 00:31:29.050 --> 00:31:32.681 it's got stepping logic. There is, there's a gem 00:31:32.681 --> 00:31:34.769 out there called wicked that helps to implement this 00:31:34.769 --> 00:31:39.241 sort of logic in a controller. I, I'm starting 00:31:39.270 --> 00:31:42.720 a gem called ultralightwizard that will do similar stuff, 00:31:42.720 --> 00:31:48.490 except it'll add the, the concept of presenters to 00:31:48.500 --> 00:31:51.280 it as well. But until then you could use 00:31:51.280 --> 00:31:53.400 wicked for the controller part. 00:31:53.400 --> 00:31:57.130 The views, you'll just have a different wizard part 00:31:57.130 --> 00:32:00.100 view, or sorry, step view. And one thing I 00:32:00.100 --> 00:32:02.850 didn't know is that this edit action, it actually, 00:32:02.850 --> 00:32:04.431 when it renders the view, you don't render and 00:32:04.440 --> 00:32:07.379 edit dot html dot erb, you polymorphically just render 00:32:07.380 --> 00:32:09.580 the step name. And then it ends up picking 00:32:09.580 --> 00:32:10.890 a view matching that step name. 00:32:10.890 --> 00:32:13.280 So if I render basic_info, it renders basic_info dot 00:32:13.280 --> 00:32:16.051 html dot erb, which contains the edit form for 00:32:16.060 --> 00:32:20.039 that step. If I render the, the detail step, 00:32:20.040 --> 00:32:23.671 then it renders detail dot html dot erb. So 00:32:23.680 --> 00:32:25.289 that's why I have these. So that way we 00:32:25.289 --> 00:32:27.260 have the views separated as well. So we achieve 00:32:27.260 --> 00:32:30.540 that goal. 00:32:30.540 --> 00:32:32.801 The form that you put can be the same 00:32:32.801 --> 00:32:35.089 on all views actually. Because you have, you're editing 00:32:35.089 --> 00:32:37.480 the same model. You're just editing different parts of 00:32:37.480 --> 00:32:40.270 that model, but it's, it's the same model on 00:32:40.280 --> 00:32:44.080 all pages. So the root model is project, but 00:32:44.080 --> 00:32:47.951 on one page I'm editing nested document content, upload 00:32:47.960 --> 00:32:50.639 the documents. On another page I'm, I'm, I'm editing 00:32:50.640 --> 00:32:52.331 just the first name and last name, and so 00:32:52.340 --> 00:32:52.800 on and so forth. 00:32:52.800 --> 00:32:54.300 So you could actually wrap this whole thing up 00:32:54.300 --> 00:32:58.979 in the helper, call it project_form_for. That's super short. 00:32:58.980 --> 00:33:00.921 Just use that. I know on one of my 00:33:00.921 --> 00:33:03.709 projects, another senior developer on the team did that, 00:33:03.709 --> 00:33:07.980 like he did that as a refactoring step. 00:33:07.980 --> 00:33:11.100 So, I mean, this is an example, but a 00:33:11.100 --> 00:33:15.311 view, a very straightforward view form, like, straight Rails. 00:33:15.320 --> 00:33:19.570 Nothing special about it. 00:33:19.570 --> 00:33:22.009 So that concludes the talk. So, I mean, I 00:33:22.040 --> 00:33:23.341 talked about why use a wizard, provide a wizard 00:33:23.341 --> 00:33:28.638 example, implementation goals, other implementations out there, and finally 00:33:28.640 --> 00:33:31.410 talked about what's my recommended approach for sticking with 00:33:31.410 --> 00:33:34.990 REST, MVC, OO, and, you know, all the things 00:33:34.990 --> 00:33:37.410 that would help ensure that your code is not 00:33:37.410 --> 00:33:40.000 maintainable only today but also a year from now, 00:33:40.000 --> 00:33:42.260 and also by other developers that will join the 00:33:42.260 --> 00:33:45.820 team with minimal training efforts, hopefully. 00:33:45.820 --> 00:33:47.911 This is the project that I launched and is 00:33:47.920 --> 00:33:49.599 empty right now, but I would like to, but 00:33:49.600 --> 00:33:51.600 I mean, you can star it and monitor it 00:33:51.600 --> 00:33:53.340 and hopefully I have something out soon. Maybe I'll 00:33:53.340 --> 00:33:55.910 do it at RailsConf. Somebody want to pair with 00:33:55.910 --> 00:33:58.390 me on this, you're welcome to. So yeah, my 00:33:58.400 --> 00:34:00.811 name is Andy Maleh. I'm the VP of Engineering 00:34:00.820 --> 00:34:06.190 at a remote only, or 100% remote option consulting 00:34:06.190 --> 00:34:09.690 company called BigAstronaut. These are my folks over here. 00:34:09.699 --> 00:34:11.250 That's Lance, CTO. 00:34:11.250 --> 00:34:15.909 Oh, oh yeah, Chief Fun Officer as well. 00:34:15.920 --> 00:34:17.840 AUDIENCE: We've got t-shirts and stickers and we're hiring. 00:34:18.179 --> 00:34:20.580 A.M.: Sweet. Yeah. Thank you everybody.