ANDY MALEH: Sorry everybody. I lost the slides.
I had to reconstruct them right now.
Right, like in ten minutes.
Ultra light and maintainable Rails wizards.
Who has written a wizard in their lifetime?
OK. It's, it's almost like the most common
web
use case, yet it's the least under, under-valued
with
regards to providing patterns for doing, like,
writing good
code in order to provide for maintainable
wizards.
A lot of the time, people write, like, multi-step
wizards, where they end up doing a lot of
copy-paste between the steps or between a
bunch of
controllers. And that makes it a hell of a
problem to maintain that code a year or two
later. And every code base is, you know, meant
to be created for a year at least. Maintenance
cost is what's really expensive. It's not,
you know,
I can write a wizard in two weeks but
will I be able to maintain it cheaply over
a year. And that, that's really why I'm giving
a talk about this subject.
So just to give you an overview, I'll be
talking about, why do we even use a wizard?
Provide an example. Some implementation goals.
The 1001 wizard
implementations out there. And, finally, I'll
talk about what
I think is a good ultra light and maintainable
wizard approach.
So first of all, we don't want to overwhelm
the user with a huge form of information,
kind
of like those government forms that we have
in
Canada. So I come from Montreal, by the way.
This is painful on a computer screen. Computers
should
enable people to do better than actual physical
paper.
So one way of tackling this problem is to
divide it into multiple steps in a wizard.
So also it's about simplifying the workflow
into multiple
steps that make them digestible, just like
this protein
shake. And finally it, it gives you the opportunity
to provide more explanation for what each
form does,
by being able to fit more information when
you
break it up across multiple pages, like what
they
do with TurboTax.
Who here has filed their taxes?
Yeah. I did not. I just did this so
I see who raised his hand.
OK. So I had a, a software architecture gig
at EarlyShare about a couple of years ago
where
I helped them launch their site. EarlyShare
is kind
of like KickStarter or Indiegogo, except it's
focused on
allowing people to do crowd investment in
businesses.
And it was a website that was being built
fast in order to catch up with some legal
laws in the U.S. that would allow crowd investment.
So I helped them launch the site and they
had, they, as part of their website, they
needed
a couple of onboarding wizards. One for investors
and
one for business people.
But there were other requirements. Like, the
business was
bootstrapped. We were only two developers.
Me as the
senior and then there was a junior with a
CTO and a designer and that's it. He wanted
us to move super fast, and I was brought
in as the Rails expert.
So I had not written a wizard in like
four years before that. Or maybe five years.
Like,
maybe since the days I did Java development.
And
when I started tackling this problem in Ruby,
you
know, I like, I went online, checked some
Google
guides and all that or StackOverflow, whatever.
And none of their approaches satisfied me.
So let's
talk about what I found.
So the wizard example, though, is basically,
you have
four steps. Step one is collect basic info.
Step
two is details, more details. Step three is
upload
some document content. Step four is just preview
before
you finish the wizard. And then once it's
done,
it shows you a summary, like a landing page
for the project that, that the business is
proposing
for investment.
OK. So, I mean, the goals I had was
the Rails server had to persist every progress
on
every step. So no, like, js client-side tricks.
That
was out of scope. I wanted it to still,
like, be RESTful, like, which is a common
issue
with wizard, like, building wizards. How to
make them
properly RESTful.
I wanted to also stick with MVC, object-oriented
principles
because we're using an object-oriented language.
So I wanted
to make sure that the code is maintainable
by
other developers going to the feature.
And then some non-functional requirements,
like productivity. So that
was part of the concern that the CTO had,
which is he wanted us to move fast, like,
really, really fast. That was part of the
reason
why he brought me in. Well, big mistake. I,
I pay attention to details and nice design
concerns.
So I will slow him down but for good
reasons.
I'll slow him down and then he'll go much
faster later on.
Still, the story does have a happy ending.
So
maintainability, by both junior and senior
developers. They had
one senior developer in Brazil as well. Which
I
just remembered. He was brought in a little
later
on.
Performance concerns. Security concerns.
So it's pretty, it's pretty basic stuff. Like,
I
mean, these are the concerns that we should
care
about whenever we build any feature, really.
So one approach that I've seen on actual code
bases, I actually saw it on a code base
that I maintained on a following project after
that
one, was one controller per wizard step.
So you create a REST resource per wizard step.
And you had multiple controllers, multiple
sets of views
and helpers. And then each controller redirects
to the
next one. So something like this. And you
could
do it either with one ActiveRecord that has
conditional
validations for each step, where it says OK,
if
step one, validate presence of name, if step
two,
validate presence of blah, blah, blah. Or
you could
have multiple ActiveRecords.
But either way, who here could find concerns
with
this approach, or at least something that
could be
improved on? Somebody volunteer? Go ahead.
AUDIENCE: [indecipherable - 00:07:10]
A.M.: And what's the concern with that? So
what
if you have a whole bunch of controllers?
AUDIENCE: [indecipherable - 00:07:16]
A.M.: OK. I mean, I've built applications
that managed
user profiles, user accounts, blog posts,
for example, whatever.
You need a controller for each one of those.
I don't think you could escape that.
So I'm gonna give other people a chance to
talk, but I do get your point. I want
to clarify it.
Go ahead.
AUDIENCE: I was gonna say repetition-
A.M.: Exactly.
AUDIENCE: Re-usability and dependencies.
A.M.: Yeah. So quite a bit of that code
is repetitive. It was just, it was always
loading
the resource. It's almost the same resource.
Actually, if
you use one ActiveRecord, it is the same resource.
And then we'd run some validations and then
it
would pass to the next controller. So, I mean,
there was quite a bit of repetition.
We try to add features a couple of months
after the, after a developer had built that
wizard
on that project, and they wanted us to deliver
something in a week, and apparently another
developer, before
I joined that team, had tried to implement
that
feature and it took him a month. And he
still couldn't do it with the, with the design
they had.
It was still, it was just taking a long
time. Like, he was still not done. And then
that guy left. So I ended up solving the
problem with another senior guy. And it was,
so,
I ended up applying this ultra light maintainable
wizard
approach that I discovered on the EarlyShares
dot com
project, and it worked out really well. So,
which,
I'll talk about a little later. But that helped
us actually develop it in, if I remember right,
it was about seven days.
Test first, and rewriting the entire thing,
also.
But it was specifically because we didn't
have that
many controllers anymore. So, we wrote a lot
less
tests so we had a lot less code to
maintain. So that was part of it.
So, another approach I've seen is one controller.
Sorry.
Oh, OK, that's just the critique. We already
went
over that. I don't think I want to go
too much into details for that cause we're
limited
on time.
But yeah, let's go next to one action and
presenter per wizard step. So, I mean, another
approach
is, OK, keep one ActiveRecord, but I've also
seen
this approach in a code base, where there
were
different, say, new_step1, create_step1, new_step2,
create_step2. So there were
just, like, eight actions on that controller,
each mimicking
the new and, and, and create, say, on the
RESTful resource.
So, although it feels RESTful, it was not
REST
anymore. It already broke out of the REST
paradigm.
So we can improve over that.
Also, it still had some repetitive code across
the
actions. So, I mean, it was, it was just
a slight improvement to the problem. Not much.
Using presenters, which is an abstraction
layer between the
ActiveRecord and the controller is an improvement
in the
sense that you can put the validations for
each
presenter per step separately and not have
conditional validations.
I'll talk more about that going forward.
So it was more something like this, where
the
controller had a whole bunch of actions that
are
connecting to presenters that are talking
to an ActiveRecord.
OK.
So I already went over the caveats of that.
OK. Who here has written a wizard with session
accumulation approach? How, how did that work
out for
you or, do you think-
AUDIENCE: That's why I'm here.
-well, I'm sorry if it sounds. Well, tell
me
why you're here. I'm curious.
AUDIENCE: Well, I mean, right now it's just
that
it's to the point where we're breaking it
down
further, it was a very basic general implementation.
And
now dealing with the fact that we have so
much session iteration that I have to pass
it
between, you know, controllers. We deal with
it from
multiple angles, and it's, I mean, I can't
put
that stuff in a model. So my controllers are
getting really out of hand.
A.M.: Exactly. Yeah. Yup. Yup. Yup.
So you end up with the live session management
code in the controller, which breaks MVC.
So if
you're not breaking REST, you break MVC. It's
really
tough. It's a tough problem.
AUDIENCE: Can you explain what session accumulation
is?
A.M.: Yes. So, actually, maybe I should have
somebody
explain that. I saw you raise your hand. Would
you mind explaining it to the audience.
AUDIENCE: Sure. It's basically, as you're
going through the
specs, that you're storing all of the information
that
needs to be in the session. So then, you
go through step
one. You gather the basic info from the form.
When submitting the form, instead of storing
that in
an ActiveRecord, you actually store it in,
in the
session, using the session helper in the,
in the
Rails controller. And then once you move to,
and
then you redirect to step two, and then you
submit that form again, and then you add more
stuff to the session.
Once you reach the last step, kind of like
what you see in this diagram, that's when
you're
ready to create the ActiveRecord. So you pass
all
of this as the params and the ActiveRecord
will
validate it and then you're done.
OK. So, so I mean as far as critique.
So reliance of session, storing objects in
the session
has implications on scalability. Usually you
want to store
ids of primitives because they're easier to
move across
servers when it's primitive data and be able
to
support multiple servers.
My understanding is if you have actual objects
in
the session, it makes it harder for you to
scale.
Controller code is more complex because of
managing session
data. Validations could get defined twice,
because you might
have to validate on every step as well, in
JavaScript or in a, in a presenter or something.
And, also present at the last step in the
model.
So again, I mean, if you're not breaking REST,
you're breaking MVC. If you're not breaking
MVC, you're
breaking duplication whatever, concerns, so,
it's a tough problem.
Hidden value accumulation. Somebody share
with us what this
is, or, it's very similar to session accumulation.
Yeah, go ahead.
AUDIENCE: Really, when you're submitting the
form at each
step you're shoving all the values from the
form
into hidden fields on the page, and then eventually,
when you hit submit, the final version will
just
set everything to the server.
A.M.: Yup.
So it's not stateful, it's stateless, because
it keeps,
like, each request has its state. You don't
have
to maintain the state in a session. So the
performance implications are gone. Like, it
has no problems
in scalability.
But you might, you, you might not want to
expose the values all the time on the, on
the user page. You can hash them or do
encoding on them, so that could improve that,
that
problem with regards to keeping form data
in a,
in hidden fields on the page every step of
the way.
But there's, yeah, I mean, but the complexity
is
still there, with having to manage the accumulation
and
having to construct the model at the end.
So it's a slight improvement.
Who here has used the state matching for a
wizard?
OK. Do you mind sharing with us your experience
with it?
AUDIENCE: I think main problem that you run
into
is that you get fat models, cause you have
to put all of the different validations into
different
states. But overall, I found that it was a
better compromise than the other options.
A.M.: Generally it is. One, yeah. So, you
create
one ActiveRecord. You make the ActiveRecord
a state machine.
You have to add a step column on that
model to support which step you're on when
it,
in order for the validation to know which
validations
to run for what step. So that way you
say, OK, on step one, if you have that
column, you'll say, OK, you'll have validations
that say,
OK, if it's step one, then I'm gonna check
for first name and last name presence. If
it's
step two I'm gonna, I'm gonna check that the
project details are present. And so on and
so
forth, depending on what each form, what field,
what
field each form contains on the, in the specific
step.
So yeah, different view per step. I already
went
over conditional validations.
To share an example, it looks something like
that,
like validate :phone, presence: true, if current_step
is shipping.
So that's just one way of doing it. There's
other better ways of doing it. There's also
gems
out there that help you with that. But that's
one way of doing it.
AUDIENCE: ActiveRecord has the ability to
run conditional validations
like that. You don't have to run a block.
A.M.: Mhmm. Yup. Yup. I'm familiar with that.
Yeah,
that's why I mentioned, there's multiple ways
of doing
that. That's just one example.
AUDIENCE: How does, how is the state machine
different
than the first, better than any of the ones
you mentioned, [indecipherable - 00:16:39]
A.M.: OK. With the other one, you could cheat
a bit and set an in memory variable that
represents the step name that you're on and
then
do that conditional validation that way, whereas
with this
one, you have, you're only working with one
model
and you don't, you haven't managed the stepping.
So
yeah, with the other approach, the controller
is doing
management of the stepping. In this one the
model
is doing the management of the stepping.
So critique. Well, first of all, it puts in
presentation concerns, like adding an extra
column to our
presenter's state, sorry, step, is not part
of the
domain, the business domain. So when you're
doing MVC,
usually the model, you're trying to put in
it
as much decoupled logic that's focused on
the business
at hand as possible in order to maintain that
separately from any view concerns or controller
concerns.
I mean, you can put anything in the model,
really. But the reason why we do that is,
in my experience, when I'm maintaining a code
base,
if I'm not having to manage view concerns
like
stepping into a state machine and a model
concern,
like the business rules of, of what happens
when,
you know, like the project description is
not present
or whatever, then it's easier for me to maintain
that model, cause I'm not thinking on one
thing
at a time. I'm not thinking multiple things
at
the same time.
Also, it makes those models smaller files,
if you
separate those concerns. You don't want a
huge model
as maintaining a state machine and maintaining
business rules
and maintaining like ten other things. You
could manage
that with splitting that into modules or concerns,
but
still, when I'm working with that model, my
head
will have the context of everything at once.
SO
it wouldn't, like, this is more of an advanced
programming thing. Like, once you've been
programming for three
years at least, you'll, you'll start noticing
that.
You'll start noticing the subtleties with
regards to mixing
concerns. Like, you start understanding why
people say follow
the single responsibility principle. I'm not
a fan of
following it dogmatically, I, but I think
it's a
good guideline, like any other guideline,
where if you
could minimize responsibilities in a model
and have it
not manage view concerns, then do that. Especially
if
MVC prescribes that as well as that's what
all
Rails developers on the field would expect.
So I think I pretty much sold that. So
yeah, so I mean, I think that makes it
pretty clear why I don't like this approach
that
much.
Also, it's a bit techy. Like, thinking of
the
wizard as a state machine is a bit computer
science-y. Like, I mean, I have a background
in
computer science, but, the, the point of anything
you
learn is to apply it in the right place
for it, and I don't feel like, when I'm
thinking about a wizard I'm thinking about
the business
problem. That's what I really want to think
about.
I don't want to think about a state machine.
As cool as that is, that's not the time
to think about it.
So I mean, a thousand and one approaches is,
there's a whole bunch of gems out there. Most
of them will simplify the things I mentioned,
or
give you better, shorter DSLs for doing the
approaches
I mentioned. But none of them achieve all
the
goals at once, of having MVC, REST, and all
of that.
I mean, to get back to that, there's REST,
MVC, OO, and then the non-functional requirements.
So, let's
go to, jump into this. I think we have
about ten minutes left.
So the first thing that, so I, I'm like,
OK, let's try to solve this wizard problem
from
scratch, like, as if I just, I'm just gonna,
like, get my tools out there. Like, the object-oriented
principles, the domain-driven design principles.
Who, who here has
read the book Domain Driven Design? Or heard
of
it, at least?
It's a book that I, my team did a
book club on, or a previous team, like six
years ago, did a book club on for the
sake of learning how to do object-oriented
design on
real business problems. Cause a lot of the
time
you learn object orientation, but it's hard
to figure
out how to create the right objects for the
real, for the right person's problem. It's,
that, that
book is a very good book on how to
tackle that.
So I, I started using those tools. Like, whatever
I learned from that book, whatever I learned
from
object-oriented programming. Whatever I learned
from, like REST. To
try to figure out what a wizard is.
Before I go ahead and talk more of what
a wizard is, what do you think a wizard,
the wizard's highest goal is?
Go ahead.
AUDIENCE: To serve views for the user.
A.M.: That's correct. So, you stumped me.
Cause I
was gonna ask about the highest goal from
the
developer's point of view, but you're right,
we should
think about the user's perspective first.
Now, let's dig, let's dig a little. No, that's
good. Let's dig a level lower. So, OK, so
we know that. That's our guiding principle,
is OK,
to serve to make things easier for the user.
But, next, what, why, why, OK, technically
what, what
is a wizard doing?
OK, that's my next question. What is a wizard
really doing? Go ahead.
AUDIENCE: Collect the proper set of validated
values.
A.M.: That's part of the work. What else?
AUDIENCE: Break down the form so they're just
small
steps.
A.M.: OK. Break down the data. Yup. Like separate
it. What else?
AUDIENCE: I was gonna say something really
similar to
that. Organize the data into, like, you know,
making
it weighted or in comprehensible sections.
A.M.: OK. And what's the end goal of running
through the entire wizard?
AUDIENCE: Creating an object.
A.M.: Yup. Pretty much. So a wizard is nothing
but the good old builder design pattern. Anybody's
heard
of it. I mean, I used to be a
hardcore Java geek and design patterns were
big in-
[audio jump] seven days - in Ruby.
But it's still good to know about things like
that, cause that pattern flashed in my head
right
away. I'm like, oh wow, a wizard is nothing
but a builder. Like, it, all it does is
like an assembly line of building a car, where
step one, you know, whatever, you put the
chassis,
second, like, step two is you add more, I
don't know, you add the doors. Step three,
you
add the windows. Four, five, and then all
of
the sudden you've built a car. So that's really
what it is.
Second part of the philosophy that I was following
is, each step in a wizard is nothing but
a partial view of that main, full object you're
building. So, one, one step is about, say
I'm
ordering a car and I want to customize that
car. Like, one step will show me the exterior
body and another will show me the interior
to
customize the interior with, whatever, leather
or mahogany front-panel,
whatever. And then, and then a third part
lets
me customize the engine.
So it's just, so all what steps are, are
views. Like, instead of thinking about them
as states
and in a state machine, this is a more
higher level way of thinking about it. It's
less
technical and more, it's just, I'm viewing
one part
of a model.
Third part is if you were to, so, with
that in mind, if you ever think about the
REST resources, it's very simple now. It's
done. Like,
you have the main model, that's the main resource.
And then you have the model parts, nested
model
part, under the main model. That's the second
resource.
That's it. You have two RESTful resources.
Very clean.
So every time you're walking through the steps
of
a wizard, you're actually editing a model
part. So,
and, so that makes it very, very clear what
the REST resource is.
Another thing in my philosophy about it was
I
did not want to have conditional validations,
cause they
make a model hard to maintain. It's harder
to
read if statements. Like, if I can have those
without if statements, it would be better.
Especially when
you come back to maintain that wizard six
months
later and then a year later and, on, on
both projects I was on, they actually added
steps
to the wizard. So they started with four steps
and then they grew to nine steps.
And the more I can separate that stuff, the,
the better. And then finally I just wanted
to
maintain the views in separate view files
as well.
I didn't want a single view file that would
do it the way I used to write code
in ASB where I'd have a crazy if-else statement
that says if step1 show this part of the
form, if step2, show me the project details,
if
step3, show me a document content upload.
I don't
want that. That's, yeah. That's ASP programming.
AUDIENCE: If they change the order of the
steps,
you want the steps [indecipherable] step three
became step
four.
A.M.: Yeah. It'll work.
OK. So, so really I mean, high level is
just, I have the main model. That's the main
resource. And then the, on the, nested under
it,
there's the four different, so, what I end
up
doing is creating four different presenters.
One per step.
Which manages the validations for that step
separately, as
well as any stepping logic related to what
happens
when you land on that page. What are the
defaults for that form? Should we initialize
the phone
number with zero, zero, zero, zeros, or should
we,
like, should, should we prefil the name from
the
logged in user account? These kinds of concerns
now
are uploaded cleanly to the model.
So we're adhering to MVC. You handle all the
wizard intelligence and business logic in
the models now.
You're not, or presenters. I mean, a presenter
is
just another form of a model that focuses
on
presented a vi- a part of a model. So,
really, I'm, I'm using it in a loose sense.
There's many ways to do presenters. I don't
care
which way.
I do have a prescribed way here, but, the
point of first to grasp is that you're operating
on a part of the model. You're not operating
on the full model. And you're doing the logic
in the, in a model, not in a controller.
And then the, the controller is the, yeah.
So
there's two of them. There's the one that
manages
the main model creation. So the first step
of
a wizard, when you create it, you create it
with a main model controller. So if I have
projects controller, I have a create action.
And then
that triggers the wizard. It'll, it'll create
it and
then redirects me to the first step.
So when it redirects me to the first step
it takes me to the edit page of model
part, the nested model part, with id_step1,
for example.
Or id basic info. So you use the step
names as the ids of that RESTful resource.
Which
is perfect REST. Like, that's, that, that
goes with,
that gives you an example of why, when people
talk about REST outside of Rails, they tell
you
REST does not relate to having a database
table.
You can, so this, this, this is an example
where the RESTful resource is a step that
is
a view of the model, but it's not a
resource. It's not a database table. It's
not a
separate database table. It's just a virtual
resource.
I need to wrap it up and then I'll
take, I'll take questions. So in a nutshell,
you
have the model resource, nested model. So
you end
up with URLs like that, which is very restful,
again, cause, like, so you have projects,
with the
id. We were using friendly id on the projects,
so the project says, yeah, so project1, then
project_parts,
and then the name of the step. And there'll
be four steps for, you know, every time you
run through that wizard. So there'll be four
ids,
only. It's a finite set. You don't have to
store it in the database.
So yeah, step names. There's id, contains
validations, yeah.
I already talked about all of that. So let's
skip.
So the routes is very, are very simple. You
just have a resources projects. It's actually
only create
and show. I left the show out. There should
be a show as well. Show is the landing
page of the project when you finish the wizard.
And then the project parts, which is edit
and
update. And it's that simple.
So, so here's the project model. It's got
the
basic definition of that model. And associations
and so
on and so forth. However, what I end up
doing is creating a presenter per wizard step,
so,
and I nest them under a directory that matches
the model name, so, project, for example.
And that's
one way of doing it. There's many ways of
doing it, but.
In this case, only step one and two had
customizations over that model. Step three
did not have
validations of its own, so I didn't even have
to create a file for it. And step four
actually didn't have anything either so I
didn't have
to create a file for it.
But yeah. Step one, you can't see the details,
but the point is that this is, these are
validations for step one, only. So that's
the first,
and then the first step, as well as some
business logic related to it, like initializing
default, like
initialize from user, which initializes from
the signed in
user.
And then there's the project detail model,
which has
a few validations, only. Only three, cause
it only
has three fields on it. So that one is
also, like, cleanly separated. Nice, easy
to maintain. So
you go back to maintain the code and it's
like, it's like, it's squeaky clean. You know
it's
like so easy. It's like the way programming
should
be.
So the project's controller, the create action,
all it
does is it creates the project and then redirects
to the edit page of the first step, which
is basic info. And then the project parts
controller
has the edit and the update and all it
does is it steps through the wizard. Now,
what
I ended up doing here is the way I
reasoned about it is that the project in MVC,
or, sorry project controller in MVC is, or
project
parts controller, is actually, although it's
a controller, it's
a model of sorts. It's a model focused on
control flow.
And stepping through a wizard is control flow.
So
then I made the controller responsible for
it. So
the, so here, at the top, it, it defines
the order of the steps, and then based on
that it walks through them. So in a way
the controller is the state machine, except
I didn't
need a state machine cause I'm not maintaining
state.
I do it with, I don't need to maintain
state. Every time we finish a step we can
redirect to the next step. And I can pass
the id of the next step RESTfully and redirect
to the next resource.
So I, I don't need to maintain what step
I'm at, on. It's always on each page. Like,
on each page, I can know, if I'm on
step two, I know that if I hit submit
it'll take me to step three next. I don't
have to, like I just know that from this
array that we define over here, which orders
the
steps in the wizard.
So, yeah, we're almost done. But yeah. I mean,
it's got stepping logic. There is, there's
a gem
out there called wicked that helps to implement
this
sort of logic in a controller. I, I'm starting
a gem called ultralightwizard that will do
similar stuff,
except it'll add the, the concept of presenters
to
it as well. But until then you could use
wicked for the controller part.
The views, you'll just have a different wizard
part
view, or sorry, step view. And one thing I
didn't know is that this edit action, it actually,
when it renders the view, you don't render
and
edit dot html dot erb, you polymorphically
just render
the step name. And then it ends up picking
a view matching that step name.
So if I render basic_info, it renders basic_info
dot
html dot erb, which contains the edit form
for
that step. If I render the, the detail step,
then it renders detail dot html dot erb. So
that's why I have these. So that way we
have the views separated as well. So we achieve
that goal.
The form that you put can be the same
on all views actually. Because you have, you're
editing
the same model. You're just editing different
parts of
that model, but it's, it's the same model
on
all pages. So the root model is project, but
on one page I'm editing nested document content,
upload
the documents. On another page I'm, I'm, I'm
editing
just the first name and last name, and so
on and so forth.
So you could actually wrap this whole thing
up
in the helper, call it project_form_for. That's
super short.
Just use that. I know on one of my
projects, another senior developer on the
team did that,
like he did that as a refactoring step.
So, I mean, this is an example, but a
view, a very straightforward view form, like,
straight Rails.
Nothing special about it.
So that concludes the talk. So, I mean, I
talked about why use a wizard, provide a wizard
example, implementation goals, other implementations
out there, and finally
talked about what's my recommended approach
for sticking with
REST, MVC, OO, and, you know, all the things
that would help ensure that your code is not
maintainable only today but also a year from
now,
and also by other developers that will join
the
team with minimal training efforts, hopefully.
This is the project that I launched and is
empty right now, but I would like to, but
I mean, you can star it and monitor it
and hopefully I have something out soon. Maybe
I'll
do it at RailsConf. Somebody want to pair
with
me on this, you're welcome to. So yeah, my
name is Andy Maleh. I'm the VP of Engineering
at a remote only, or 100% remote option consulting
company called BigAstronaut. These are my
folks over here.
That's Lance, CTO.
Oh, oh yeah, Chief Fun Officer as well.
AUDIENCE: We've got t-shirts and stickers
and we're hiring.
A.M.: Sweet. Yeah. Thank you everybody.