It's a good way of accomplishing that kind of situation. However, I'd rather suggest what you mentioned first: split the various fields into fieldsets and use Javascript; sounds much easier, the same visual process is achieved and the Rails code is kept clean.

In either way, you wanted to present a 100% Rails way of accomplishing it and you did. Nice!

Nice for a "first attempt", but it really needs refactoring or separation of concerns. I don't like how both the model and controller are essentially providing view functionality.

I think this could be quite easily plugin/gem-ified with a Module which alters the common use case of if/else on #save. That is, an alias_method_chain on #save which is altered to return false if there are outstanding steps (where steps are defined via methods made available through said module).

I agree with @Marc since there are a few MVC "violations" here. In particular there is a lot of controller-specific functionality imbedded in the model which would make it very difficult to re-use the model with a different controller/view e.g. taking an order via a webservice. But as a practical solution it works.

I've finally caught up on Railscasts! These are awesome. I just wanted to let you know that the recent videos haven't been showing up very well using VLC on Ubuntu. I don't know what you are doing differently but it started around ep. 212.

I kind of get the whole 'mvc violation' thing, but I still like your solution. Like you said it could use some refactoring but it's really not that bad. The whole skinny controller thing is a bit ridiculous and people go a bid overboard IMHO.

I've often wondered how I would achieve this, but have never tried it because I too like the 'one form' approach. I tend to ask for as little information is required to complete the transaction, then ask for more when you need later, it appears to be less invasive to one's privacy.

I don't think the JS only solution is a good one. The wizard should be able to fall-back to Rails; when JS is not available. And doing validations in JS could mean crappy data being stored if JS was turned off.

*Thank you* for exploring this, even if it is literally a couple of years too late for me -- I could have used this back in 2007 and 2008! But it helps show how to avoid and/or clean up some of the egregious code I perpetrated back then, in my ignorance...

Would we not have problems using the session, if the user opened a new window and wanted to edit two products at the same time?

Instead of storing the variables in the session, we could equally store them in hidden fields. We could create another model object called old_product, and then store its properties in hidden fields in the form.

When I started learning RoR this was the first project I had but I went a different route that took way longer than it should have and way to much code. This is completely simplified compared to what I have. I'll have to implement this method of the multi-step form. Thanks for doing this. Looking forward to the refactoring.

I generally do something similar, but prefer to wrap all the workflow logic into separate module/classes that just check the state of one or more model objects.

For example you might have an OrderWorkflow class which has a #steps method that returns an array of FirstStep/SecondStep etc. objects. Each step object implements a complete? method & the OrderWorkflow#current_step simply returns the first object that is not complete.

One advantage of that is that you can take advantage of rail's partial rendering on objects to provide different views for each step.

+1 vote for a refactored controller, if you want to bang out a quickie. ;) Also, I think it might be a good idea to show storing the params in the DB and using the update action rather than sessions when you do the refactored controller.

Thank you so much, it was just what I was looking for!
Although I have so problems that I had fix:
- didn't recognized <% title "New Order" %> so I had to run script/generate nifty_layout
- I got this error:
Missing template shipping_step.erb in view path .../app/views:
so I have to put <%= render :partial => "#{@order.current_step}_step", :locals => { :f => f } %> in new.html.erb
- render "new" didn't work for me either, changed to ender :action => 'new'
-for first_step? and last_step? : self.current_step, didn't work with only current_step

I experience some strange behaviours when playing around with this multistep form. Sometimes, when pressing back to change a step, it jumps two steps forward when pressing next afterwards. Somebody else who sees this in his form?

I like this approach, but one problem is that it breaks the browser forward/back/reload buttons. So for instance, clicking continue will take you forward one step, and then clicking 'reload' will then mistakenly take you forward another step. This can be solved by storing the current step in the view rather than the session - I've shown the changes here: http://pastie.org/1084054

Great tutorial! Is there any way to combine this with your complex form episodes. Basically I'm working on a multi-step, multi-modal app and am kinda stumpped on trying to get different modals in each step of the process.

Well i started as a RoR developer now active PHP developer (but with rails 3 i definitely consider returning) i use hidden fields to accomplish this task. Since you are submitting the values going back and forward the model object is being populated with the previous values with one difference you always have to have all of the fields hidden (showing only the once that are getting populated by the step). Sorry for this late response but i hope it helps.
Anyway thanks a lot for screencasting about rails, if it wasn't for railscasts i dont think that rails would get this popularity which definitely deserves.

Coming to this 12 months later, but did want to pitch in with having tried this, I found it better to store the current step in the form, not the session, to prevent refreshes behaving oddly.

However, I see Si Wilkins posted the same 9 months ago - what's more the code snippet he linked to showed me a couple of tidyups I hadn't thought of either !

Highly recommend adding these tweaks onto the end, for anyone else following this approach, as aside from a slightly invaded model object, you do get a nice wizard approach without needed to learn a new framework library addon (not that I've found one of them for Rails3 yet)

Late to the party -- I like Ryan's approach but was troubled by the complexity of the create() method. My modified approach has a Wizard model that saves the current_step as a db field (so it's preserved across sessions) and saves an instance before starting. From there, everything is done in the upate() method, so the controller simplifies down to:

are you able to do edit and update using your code? if yes then please help me to do same. I am stuck at edit and update . whenever I'm trying to edit it showing first step that is okay but after pressing the continue button form saves and not going to next step. what should i do?

Can anyone point me in the right direction getting this to work with file uploading? I've tried just sort of mashing file uploading in there, but you can't store files in a session variable (you get type error, can't dump file).

for anyone curious, my solution to this problem was to drop the deep_merge approach entirely. Instead of storing all the model information in the session_params, I just created the model in the "first step" then called update_attributes on it in the following steps, effectively "saving" it between steps. This isn't exactly the same behavior shown in this cast, but it's actually better in my case.

Hi There, thanks for the rail cast I am wondering if anyone has had experience with using ActiveModel like the #219 Rails Cast as it would be better if I could do this without the Active Record database creation, as well as possibly removing the sessions to be used in memcache instead, it seems there isn't a lot of info on this and would be very appreciative for any help someone can offer!

how is it possible to a repeat a step? I've combined this Railscast with the Railstcast dealing with nested attributes.

For example: In the first form I will create a question. In the next step I will create an answer and can choose between "Create a 2. Seconds Answer" or "Finish". If I choose to create a second or third answer this should happen in a new form until I decide to finish this record.

post published is very helpfull for me.Here you have carried out on single model.How to implement it for example like if User model has many association with Address model.I want user information in one form and Address information in Another form.Please explain me

hey friends i got the solution on multi-step form edit and update methods something like this bellow->

after watching this video I created two step form and it was working greatly thanks to Sir Ryan, but after while when i was went for editing and update the form it doesn't working.
It renders on the first step successfully but when i click on the continue button the form goes to update and skips the next step. That was really big issue with my app.

So after very long efforts I found solution may be it is wrong way but for me its working smoothly lets see how it works->

First of all gave the "name: some name" to all buttons n that form's each button.
then make extra view file (not partial) for last step (i had only 2 steps) so for second step as same as your partial for second step.
now then come back to your controller's update method and write code

As is known to all, writing is an important and necessary skill for all students. However, many students don't really understand the true importance of writing, as they just consider writing as a task of exam. As far as I am concerned, writing has deeper importance in many ways.Firstly, improving our ability of using words is a basic function of writing. For example, in order to write a good English composition, we must use every word carefully as much as possible to ensure its correctness. In the process, we have improved our ability of using words and writing skills imperceptibly. In this aspect, writing is a good way to strengthen our ability.Moreover, writing is an effective way to enlarge our vocabulary. Different compositions we write need different vocabularies. Therefore, the more compositions we write, the more vocabularies we get.www.nikemax.shoeswww.mkpee.comwww.nikeshoesales.comwww.shoesmaxs.comwww.lightupshoe.salewww.mkfact.comwww.mkzho.comwww.mkuker.comwww.nikeyeah.comwww.nikebtc.com

After read a couple of the articles on your website these few days, and I truly like your style of blogging. I tag it to my favorites internet site list and will be checking back soon. Please check out my web site also and let me know what you think.