How do CRUD and REST work for a wizard-style application?

I’m rewriting an application with the intention to use the elegant CRUD
and REST design principles as outlined by DHH in his RailsConf
Keynote[1].

The question is: how do you use those principles for an application
that is of a sequential nature?

The application works much like an MS Windows wizard: user begins at
screen foo. After doing (or not) some stuff in screen foo, he is taken
to screen bar, and from there to screen baz, etc. (the order of the
screens may be altered and/or reversed). The application is essentially
about walking the user through a sequential procedure.

A common solution would be to define each screen as an action. I.e. the
ProcedureController would contain actions #foo, #bar, #baz, etc. This
obviously does not remotely resemble anything like the above mentioned
CRUD/REST principles, in particular the neat “7 standard actions per
controller” design[2].

Can the CRUD/REST model, in whole or part, be applied such an
application?

-Alder

[1]
http://blog.scribestudio.com/articles/2006/07/09/david-heinemeier-hansson-railsconf-2006-keynote-address

[2] index, new, create, show, edit, update, and destroy, see:
http://scottraymond.net/articles/2006/07/20/refactoring-to-rest

A common solution would be to define each screen as an action. I.e. the
ProcedureController would contain actions #foo, #bar, #baz, etc. This
obviously does not remotely resemble anything like the above mentioned
CRUD/REST principles, in particular the neat “7 standard actions per
controller” design[2].

Hi

the first thing Ill have to say is that I havent actually worked with
this technique yet. Ive just watched the Keynote and read the S. Raymond
article, so YMMV.

The thing is tho, Im trying to create exactly that - a wizard - at the
moment. And I think its not too hard actually.

First thing: The problem with an action for each step in the wizard. I
personally dont find that too bad – even Scott R. does it, with
his about controller, which has a lot of non-standard actions. However,
if you want to avoid that, you could, I think simply add a case
statement into the view of your index action, displaying only that part
of the wizard you need at the moment, like so:

case params[:page]
when 2

display page 2

when 3

display page 3

else

display page 1

end

Second thing: The problem with standard actions. That should be possible
if you dont actually save the data to the database as long as the wizard
is running, but into a session instead. Then, when the user has entered
everything, he/she can view all the data and either go back and change
something, or click the final “Save this” button, which points to a
standard “create” action. This behaviour is also much more wizard-like,
imo – an install wizard, for example, also only starts to actually
install once youve given it all the information it wants.

Again, your mileage may vary. I havent really tried any of this stuff
out (yet).

Hoping to Help,
Daniel

My first thought after reading your email was: DON’T PUT IT IN SESSION!!

And then I remembered, Rails can put session into the database to
create the “share-nothing” environment. So if the wizard should be
completed in a short amount of time, session works. Yea Rails!

I am preparing to create a wizard myself. I am planning to use
acts_as_state_machine to keep track of what page the user was on. This
would allow the user to save the information to the database for
extended periods of time (a requirement of my application) before
completing the wizard. So if your user would be completing the wizard
over several sessions, this may be a better route to take.

Carl

Carl F. wrote:

completing the wizard. So if your user would be completing the wizard
over several sessions, this may be a better route to take.

Carl

Have you looked at the Acts as Wizard plugin?

http://wiki.rubyonrails.org/rails/pages/Acts+As+Wizard+Plugin

-Alder

Daniel J. wrote:

this technique yet. Ive just watched the Keynote and read the S. Raymond
article, so YMMV.

The thing is tho, Im trying to create exactly that - a wizard - at the
moment. And I think its not too hard actually.

Take a look at the Acts as Wizard plugin.

http://wiki.rubyonrails.org/rails/pages/Acts+As+Wizard+Plugin

First thing: The problem with an action for each step in the wizard. I
personally dont find that too bad – even Scott R. does it, with
his about controller, which has a lot of non-standard actions. However,

Most of Raymond’s application is modular and object-focused - a classic
fit for the CRUD/REST model. It’s a far cry from the sequential,
proocedure oriented nature of a tutorial.

And yes, you can see the CRUD/REST model breaks on stuff that deviates
from the above (modular and object-focused) norm.

display page 1

end

An idea I like is to instead have Tutorial as a model, with a
TutorialsController and the usual crud actions, so:

example.com/tutorials/23 # display tutorial with ID 23

Pages are “cuts” of tutorial objects, so we can use the nifty new ;
from Simply Restful to fethc any particular page, so:

example.com/tutorials/23;42 # display page 42 of the tutorial with ID
23

Second thing: The problem with standard actions. That should be possible
if you dont actually save the data to the database as long as the wizard
is running, but into a session instead. Then, when the user has entered
everything, he/she can view all the data and either go back and change
something, or click the final “Save this” button, which points to a
standard “create” action. This behaviour is also much more wizard-like,
imo – an install wizard, for example, also only starts to actually
install once youve given it all the information it wants.

Interesting idea, thanks. It does make things easier.

Daniel J. wrote:

Second thing: The problem with standard actions. That should be possible
if you dont actually save the data to the database as long as the wizard
is running, but into a session instead. Then, when the user has entered

What on earth is wrong with saving to the database? If you model
correctly you will have a Script and Submitted Script. Why shouldn’t a
user be able to come back to a partially completed script tomorrow?

The session system is merely there to provide an illusion of state
between what are actually unconnected HTTP requests to various
webservers. It should really be nothing more than a bunch of pointers
to stuff stored in the database.

I wrote up a little plugin for doing wizard like work, you can check it
out at:
http://svn.trac.washington.edu/svn/plugins/multi_stage_wizard/

The easiest way to use it is to persist the object in the user’s
session, however you can get around that if you want to. You might
also look into Tableless Models if you are using your wizard to model a
process instead of incrementally filling out a record.

Hope that helps, send me an email if you have any questions,
.adam

On 9/11/06, NeilW [email protected] wrote:

user be able to come back to a partially completed script tomorrow?
Because validations on models assume the model is complete. If you
have “validates_presence_of :foo”, when :foo isn’t going to be filled
out until some later page in your multi-page-wizard form, you CAN’T
save the model using AR before that page.


The major cause of problems are solutions. – Eric Severeid

Not true. Validations are optional. You can save without validating, or
you
can validate conditionally. From the API:

validates_presence_of :foo, :if => Proc.new { |user| user.signup_step >
2 })

Validations have default behaviors, but that does not mean that you
cannot
do more. One might consider a different approach to modeling records
for
multi-step processes. Just don’t let the way you think Rails works
dictate
how you model your application.

On 9/11/06, Brian H. [email protected] wrote:

Not true. Validations are optional. You can save without validating, or you
can validate conditionally. From the API:

validates_presence_of :foo, :if => Proc.new { |user| user.signup_step > 2 })

Validations have default behaviors, but that does not mean that you cannot
do more. One might consider a different approach to modeling records for
multi-step processes. Just don’t let the way you think Rails works dictate
how you model your application.

Fair enough; I hadn’t looked at them closely enough to have seen that.
Thanks for that information, Brian.

Michael


At times one remains faithful to a cause only because its opponents do
not cease to be insipid. – Friedrich Nietzsche

Michael C. wrote:

I’m probably missing something basic here; what is it?

Your model is trying to do two things at once. You have a completed
script and a script. Those are two different states of a model object,
and the model should reflect that - two model classes and an
inheritance hierarchy.

NeilW

On 9/12/06, NeilW [email protected] wrote:

Michael C. wrote:

I’m probably missing something basic here; what is it?

Your model is trying to do two things at once. You have a completed
script and a script. Those are two different states of a model object,
and the model should reflect that - two model classes and an
inheritance hierarchy.

Interesting; I’ll ponder that and see if it fits better what I’m
doing. Thanks for that insight, Neil.

Michael


If the code and the comments disagree, then both are probably wrong.
–Norm Schryer

I did this once using javascript and partials. When step 1 was finished
and
someone pressed next I just hid the step 1 DIV and showed step 2. That
way
when all the steps are done and Finish is pressed all the form data is
submitted at once although it’s DIV container is hidden.

Jon Gretar B.
http://www.jongretar.net/

There’s a really neat side-effect of this approach…
If you placed the “go to step 2” button on the page using JS, then users
without JS would still be able to use the wizard… though it would
appear
as one big long form.

I’ve used that approach many times.

On 9/12/06, Brian H. [email protected] wrote:

There’s a really neat side-effect of this approach…
If you placed the “go to step 2” button on the page using JS, then users
without JS would still be able to use the wizard… though it would appear
as one big long form.

Sure. Although like I used it it would need some altering to work
without
JS. I used partials alongside it. For example in this registration page
I
used you entered requested username and email and before hiding the DIV
it
checked if that username was taken and only displayed the next step
after
that validation. Using this method also allowed me to minimize the
amount of
actions I created in the controller as I prefer creating as few of those
as
humanly possible. Using this method I got away with creating just one
“create” controller that sensed between PUT and POST and did some
in-form
validation using AJAX and a partial. It’s a little hassle to get going
in
the beginning but the code looked so much better.

Jon Gretar B.
http://www.jongretar.net/

On 9/11/06, Brian H. [email protected] wrote:

Not true. Validations are optional. You can save without validating, or you
can validate conditionally. From the API:

validates_presence_of :foo, :if => Proc.new { |user| user.signup_step > 2 })

The more I think about this, the less I like it. What if my model
participates in a number of different flows/wizards? I’ll need to
have a Proc that tests 1 of n conditions? No thanks.
I want to be able to tell /save/ to validate or not, not the model.
This way ties the model to the controller.

I guess I can have an attribute on the model that determines if
validation should occur, and set that before calling save, but that
feels… wrong.

I’m probably missing something basic here; what is it?