Advice: Managing errors w/"too big for session" objects


#1

All,

I ran into a situation where I was receiving “marshal data too short”
errors on my Apache/FCGI combination (yes, I know about Mongrel, etc.)
when I was displaying errors using the standard scaffolding error
scheme. I solved this problem but wanted some advice/feedback on my
solution.

Here is the original code from my controller that I was using to handle
the errors:

begin
@current_job.set_list_relationships(params[:current_job][:target_list_ids])
@current_job.update_attributes!(params[:current_job])
rescue
flash[:current_job] = @current_job
return redirect_to( :action => ‘job_params’ )
end

The problem with this was that @current_job is a huge object with a big
object graph and this was blowing up my session (since flash is a
session object) when I would do the redirect back to ‘job_params’.

My solution is below. I created a clone of the @current_job object and
then populated that new object’s errors array (since AR::Base.clone does
only a shallow copy). Then, of course, my view executes
error_messages_for() on what’s in flash[:job].

I have a couple of questions:

  1. Is the loop on errors.each_full the best way to handle getting the
    errors onto the new object? I couldn’t see a way to just copy the
    errors from @current_job to flash[:job] wholesale.

  2. Is there a better way to handle this? I don’t think so given that
    the errors array has to be handled somehow.

  3. Does it make sense, in general, to “render” your errors but redirect
    on success? In this particular case, I really do have to redirect even
    on the errors because the destination page is performing an AJAX call
    triggered by an “onload” event. But oftentimes, I could see one just
    rendering in the error case since the instance variables are already
    available for the destination view.

begin
@current_job.set_list_relationships(params[:current_job][:target_list_ids])
@current_job.update_attributes!(params[:current_job])
rescue
flash[:job] = @current_job.clone
@current_job.errors.each_full do |err|
flash[:job].errors.add_to_base(err)
end
return redirect_to( :action => ‘job_params’ )
end

Thanks,
Wes