Search code examples
ruby-on-railspaper-trail-gem

"Redo" suddenly failing.


Awhile ago, I implemented an "undo" and "redo" button like in this railscasts on the paper_trail gem. Everything worked great until today when the "redo" stopped working. I haven't been able to figure out why.

Here is the relevant controller action:

  def revert
  @version = PaperTrail::Version.find(params[:id])
    if @version.reify
      @version.reify.save!(:validate => false)
      view_context.reify_associations(@version)
    else
      @version.item.destroy
    end
    link_name = params[:redo] == "true" ? "undo" : "redo"
    link = view_context.link_to(link_name, revert_version_path(@version.next, :redo => !params[:redo]), :method => :post)
    if @version.event == "create"
      flash[:success] = "Undid #{@version.event}. #{link}"
      redirect_to :controller => session[:controller], action: :index
    else
      flash[:success] = "Undid #{@version.event}. #{link}"
      redirect_to :back
    end

  end

It fails on the line: link = view_context.link_to(link_name, revert_version_path(@version.next, :redo => !params[:redo]), :method => :post)

With an error: ActionController:UrlGenerationError ... No route matches {:action=>"revert", :controller=>"versions", :format=>nil, :id=>nil, :redo=>false} missing required keys: [:id].
So, obviously, I followed the error to see why the :id wasn't being passed in, but it is.

In the parameters:

{"_method"=>"post", "authenticity_token"=>"6/B1YDXqZ62+DqMMdcYTfCTIJGaVvc1RjKmxWW2GkeQ=", "redo"=>"true", "id"=>"29"}

The id is clearly defined and the first line of this controller finds the corresponding version in the table based on that id.

I cannot figure out what is wrong here so any help would be greatly appreciated.


Solution

  • For anyone finding this later on, the issue I was having was the first statement of my conditional (@version.reify) never returned nil. This is because I had overwritten the object attribute to add additional information to create events. To solve the problem, I simply changed the conditional to check the type of event, i.e.

    if @version.event == "create"
    ...
    end
    

    PaperTrail's reify method looks at the object attribute of @version and recreates the object from the serialization. It returns nil whenever the object field is nil, otherwise it will return the object it unserialized.