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