How Redisplay Failed User Data in Form?

Forms. Specifically entering data, submitting, discovering validation error, redisplaying the form with user's entered data and error messages.

I know how I would approach it left to my own devices (described below), but wondering if there's an idiomatic Rails way.

The classic "How To" stuff shows setting values of form elements directly from models. Well, that's spiffy if nothing goes wrong, but in the above sequence of events, that approach doesn't work.

Normally, in the controller I would load the model with data, I would then create a form data object ("FDO") with a placeholder for each field that applies to the user-entered data in the form. I would populate the HTML input values with the contents of this FDO. So, value="<%= fdo.firstName %>" not value="<%= model.firstName %>"

To populate the FDO I test params to see if the form had already been submitted. If yes, I populate the FDO by copying values from params. If not, I populate the FDO by copying original data from the model.

This way the form sees virgin data from the database/model when the form is first displayed, and then the tainted data from user input if the form is redisplayed.

Does Rails have anything built in for this process, or is the developer left to implement his own system like I describe above (which of course is fine with me).

-- gw (www.railsdev.ws)

Hello Greg,

It sounds like a lot of work :slight_smile: Here is a typical method in a controller:

  def update     @post = Post.new(params[:post])     if @post.save         redirect_to post_path(@post)     else        render :action => 'edit'   end

If the save is not successful it redisplays the edit view (form).

Would this work for your requirements? What are your concerns displaying properties from the model?

What are your concerns displaying properties from the model?

I have the redisplay of the edit form working fine, but if there's a validation error, the form is showing the original data coming from the database, and not the data that was just entered into the form.

So, in a field for numbers let's say the form originally displays a value of 3 (which came from the db). The user edits it and writes "two" -- right now when the validation fails, and we cycle back to the edit form, it is redisplaying 3 and not "two". We don't want the user to have to edit the form all over again, so we want data from the params values has to populate the HTML value attributes.

Something has to be in charge of using the database data the first time, but use the params data the second time around. The form is an interim container until we approve everything, and then the model gets updated.

-- gw

Sorry Greg, I screwed that example up:

It should have been something like this:

def update     @post = Post.find(params[:id)     @post.attributes = params[:post]     if @post.save         redirect_to post_path(@post)     else        render :action => 'edit'   end

Anyway, following something this will mean that the action (or view) will be rendered (if the model cannot be saved), displaying the data that the user entered, because the view will be feeding off the instance variable for the model with the attributes passed from user input (not the original values of the model), e.g.:

value = "<%= @post.title %>"

if this is not working for you perhaps you could post some code from your controller.

Cheers, Nicholas

Hmm. I've always validated before updating the model. Philosophically
it seems undesireable to stuff the model with data that has not been
vetted.

In a simplistic model that's just a quick exchange of data with a one
page turn-around, I suppose it doesn't really matter so long as the
save is prevented.

I guess if that's the accepted way, I'll give that a shot.

-- gw

Greg,

Yes, it's the Rails way to assign to the attributes and save/validate the model. If the model is not valid then it will not save. The save method calls #valid? to see if it has been saved or not - you can call this method as well - e.g. @post.valid?.

Cheers, Nicholas

I implemented everything based on that approach and have it all working.

Thanks much!

-- gw