Multipage Forms

I think this may actually be an object oriented programming question. Not only am I new to Ruby and Rails, but I'm also coming from a functional PHP background, so this whole OO approach to web programming is new to me.

I have a three page registration form and I am trying to determine best practices for managing the data across forms in a session. I would like each form to validate before passing the user along to the next page. The data will be ultimately be distributed across 6 different tables, so the validation criteria for the registration form is spread accross the 6 repective model objects.

My thought is to create a non-ActiveRecord model called "Registration" and have it create the various model objects as instance variables upon instantiation:

class Registration   def initialize     @member = Member.new     @membership = Membership.new     @donations = Donation.new     ...   end end

and then save this in this object in the session. When I need to validate the form data, I could do something like this in the registration controller:

@registration = session[:registration] ||= Registration.new @member = @registration.member @member.attributes = params[:member] redirect_to :action => 'next_page' if @member.valid?

That way, I can still use the model (and ActiveRecord) to handle the nitty gritty of form validation and I only need to manage one object in the session. Also, if I have a form with data that belongs in three seperate models how do I validate that data across the various models? My guess is to add something like this in my registration model:

def valid?   @member.valid?   @membership.valid?   @donation.valid?   @errors = @member.errors.merge(@membership.errors).merge(@donation.errors) end

And then this in the view

<%= error_messages_for 'registration' %>

Does that look right? I'd like to know if these are common best practices for handling multipage forms in Rails and if not, how do the rest of you do it?

Thanks, Greg

There is one very important issue to keep in mind here: ActiveRecord models aren’t fully serializable. This means that you can’t create a model and throw it into the session without saving, as you will lose the data and the app will probably crash. I recently had to deal with this same situation (model information over like 6 pages) and it took us a while to figure out a good solution. Unfortunately the best solution was keeping our own hash in the session and only when we are done collecting all of the data do we pull those values into a new model for validation and saving.

If you are ok saving a partially complete AR object, then you’re fine using the session (for note, only the ID is guarenteed to be saved, AR repolls from the database when needed).

Hope that helps. Just remember that even though placing unsaved AR objects in the session may be working for you, there is no guarentee that it will work anywhere else.

Jason

I try to avoid using the session as much as possible for these. Your forms are bound to models with validation, so just let them do the work for you. You can do all sorts of cool things to avoid validating fields until you need to.

I don’t think there’s any reason to make your own model that you’ll store in session just to wrap existing models. Use them as they are and save the records. If, for some reason, you don’t want to save the record (incomplete transaction, etc) you could just store the object directly to the session and only save it upon completion.

However, for a shopping cart, there’s actually some value in saving as they go becuase you’d have some data you could look at to help find out why people left your store in the middle of a transaction. Just add an additional status field to your table… 0 for default, 1 for submitted, 2 for in process, 3 for fulfillment, 4 for complete, 5 for cancelled… etc

This is just off the top of my head though. There are lots of ways to do this.