0

Following the helpful tutorial in Railscasts #38 http://railscasts.com/episodes/38-multibutton-form I set up a "Preview" button for my "New"/"Create" controller actions.

But when I use the same method for "Edit"/"Update" there seems to be a problem.

I can't seem to get my form to persist.

Here's what my controller looks like:

def update
    stylesheets << 'feature'

    @feature = Feature.find(params[:id])

    case params[:submit]
        when "Preview" 
            render :action => "edit"
        return

        when "Update" 
            respond_to do |format|
                if @feature.update_attributes(params[:feature])
                    flash[:notice] = 'Feature was successfully updated.'
                    format.html { redirect_to(features_path) }
                    format.xml  { head :ok }
                else
                    format.html { render :action => "edit" }
                    format.xml  { render :xml => @feature.errors, :status => :unprocessable_entity }
                end
            end
        return
    end

end

When I hit the preview button, I am returned to an editing screen as expected, but my edits don't persist. Any tips? Curious, as this works fine for previewing New objects.

isthmuses
  • 1,316
  • 1
  • 17
  • 27
  • Without a hard look, try `render :action => "edit" and return`. If that's not it, the value after `when` needs to correspond to the name you have given the button, and that will appear in the params array -- check the `logs/development.log` and make sure the name you're getting is correct. – Tom Harrison Nov 20 '12 at 00:56

1 Answers1

2

What's happening here is that you're not actually applying the changes the user made to the in-memory model before rendering your view, so the changes get lost.

Try changing your 'Preview' case like this:

when "Preview"
  @feature.attributes = params[:feature]
  render :action => "edit"
  return

One thing I would say is that I'd also consider splitting that method up a bit to make it easier to read and test. Something like this:

before_filter :set_stylesheets

def set_stylesheets
  stylesheets << 'feature'
end

def update
  @feature = Feature.find(params[:id])
  preview if params[:submit] == 'Preview'
  apply_update if params[:submit] == 'Update'
end

def preview
  @feature.attributes = params[:feature]
  render :action => "edit"
  return
end

def apply_update
  # Rest of update action here.
end

This helps you keep your tests simple and focussed on one method at a time, and should make the code easier to maintain.

Paul Russell
  • 4,727
  • 1
  • 30
  • 28
  • Thank you! I knew there must be a method for getting the params into the mix, but sensed that building a Feature.new(params[:feature]) wasn't quite right. The attributes method did the magic! Thank you, Paul! – isthmuses Nov 20 '12 at 01:06