ruby-on-railsrestroutesacts-as-versioned

Rails & Acts-as-versioned: How would you restfully revert records?


How can you revert records in a way that respects REST conventions and routing?

I am looking for examples of how to setup my routes.rb and build the link & controller action to do the revert. All the examples I have found are pre-REST rails.

My understanding is that I need to have revert_to_version function in my resource controller.


Solution

  • I've never used acts-as-versioned in particular, but when I come across similar scenarios, the way I usually solve it is by reification of the attribute. In other words, I'd create a new resource only for the actual version number of the resource.

    Eg.

    /resources/:id/actual_version
    

    would point to the actual version number of the resource with id :id. Then to change the actual version, we can just PUT desired number to it.

    PUT /resources/:id/actual_version
    :version = 123
    

    would revert our resource to the version 123.

    As a convention, I'd use something like "last-but-one" as a value of :version to refer to the version that preceded the actual one.

    Then, to rollback the actual version, we can just do:

    PUT /resources/:id/actual_version
    :version=last-but-one
    

    --

    Expanding my own answer:

    In routes.rb we can do something like:

      map.connect   '/resources/:id/actual_version', :controller => 'resources', :action => 'set_version', :conditions => { :method => :put } 
    

    And in resources_controller.rb:

    def set_version
      @resource = Resource.find_by_id(params[:id])
      if params[:version] && @resource
        version = params[:version] == "last-but-one" ? @resource.versions.last : params[:version]
        if @resource.revert_to(version)
          # Success, everything went fine!
        else
          # Error, the resource couldn't be reverted - unexisting version?
        end
      else
        # Error, version number or resource id is missing.
      end
    end
    

    Hope that clarified my previous thoughts a bit. ;)