Search code examples
ruby-on-railsruby-on-rails-3ruby-on-rails-3.1preview

How to save (or update) an object without a form


I implemented a standard Rails (and RESTful) process to CRUD an object.

The only customization (or "configuration over convention") I need is the following:

After a standard edit form, instead of showing the object, I show its "preview" (which simply is the action "show" with some adjustments in the view and with "object.status = preview") at this point I need to allow the user to "confirm" or "save" this previewed object with a simple button. Like if the user where submitting again the edit form (or the same object) but without having to see it again. Just hitting a "Confirm" button.

(In the update action I check if the object.status is "preview" and if so I consider it confirmed and I show a confirmation message instead of the preview).

My only missing piece is the "Confirm" button in the "show" view to PUT the @object.

How can I implement it?

PS: I know the best practice is to show the preview in the edit view (just like in stackoverflow.com) but in my app the design is very important so I need to provide the most close to reality as possible preview.


Solution

  • You probably don't need another action, just another view. Basically the flow is something like this:

    1. User lands on the edit page. The form is rendered. They edit it and submit it…
    2. The Update action is called. No "previewed" parameter is available, so the "preview" view is rendered instead of actually saving the form.
    3. The preview shows the preview (like show), but it also has a copy of the form with the fields hidden (via CSS) and an additional hidden value called "previewed" with a value of "1".
    4. When the user clicks "Confirm" the form is submitted right back to the update action that then sees the "previewed" parameter and actually saves the object and redirects to the show page.

    Here's the controller code, since it's the most complicated piece:

    # controller
    def show
      @widget = Widget.new
    end
    
    def edit
      @widget = Widget.find(params[:id])
    end
    
    def update
      previewed = params.delete(:previewed)
    
      @widget = Widget.find(params[:id])
      @widget.attributes = params
    
      if @widget.valid? && previewed
        @widget.save!
        redirect_to widget_path(@widget), :notice => 'Yay'
      elsif @widget.valid?
        render :preview
      else
        render :edit
      end
    end