Revision Control with Paperclip - Rails
09 Apr 14
In this tutorial I will show you how to manage file versioning / revisions in Ruby on Rails using Paperclip and vestal_versions gems.
There is this project I did late last year. The project involved making a web application in ruby on rails where users could request logos to be made for them. The admin could then get a notification after a request and make a logo as specified by the user. The admin could then submit a finished logo upon which they would then collaborate with the user to refine it. The app was therefore supposed to keep a revision of those logos so that users could track how the logo changed over time.
In this tutorial I am going to guide you through how I went about in implementing this functionality using
paperclip and vestal_versions gems. I will show everything from scratch so lets start by creating a new rails application
# create new rails application
$ rails new revision-control
# change directory to our new rails app
$ cd revision-control
We now add our two gems to our Gemfile and run the bundle install command to install them
We need a model upon which these gems can act on. How about we scaffold a logo model to get us up fast and running.
$ rails g scaffold Logo name:string
Run rake db:migrate command migrate the database. After that is done we need to generate migration files for both paperclip and vestal versions so that the respective tables and columns are added to our database models.
# for paperclip
$ rails g paperclip logo image
# for vestal versions
$ rails generate vestal_versions:migration
We then run our migrations
$ rake db:migrate
After the migrations run successfully we now need to version our Logo model. We do this by simply adding versioned to our logo class. We must also add paperclip to our model. Our logo model should look like so:
Next, we need to edit our shared form partial and add our file upload field and make the form accept file uploads by making it multipart
http://0.0.0.0:3000/logos/new we should now have something similar to this:
With this, lets not forget to add our new image param to our list of permitted params. In our users controller:
Next we need to add the version number on the logo show action page. To do this we just need to show the logo's version.
Now how about we upload our first image?
Thats looks like it worked perfectly!!! Now, the interesting part of this is we have to tell paperclip not to delete attachements when a record is edited. We do this by creating a paperclip monkey patch and place it within our initializers directory
Because attachments are defined at the class level, Paperclip interpolates the symbols in your strings using it's own interpolation library. You can create your own interpolations using this library. To do this we add a field to the model called version and configure paperclip path to take care of our versioned files.
If you're following along, we changed paths for paperclip attachements and for the new initializer to take effet we need to restart our rails app. Lets also reset the database to upload logos a fresh.
$ rake db:reset
# restart server
$ rails server
Now I've re-uploaded my initial 'logo', so should you if your following along. Now lets edit and upload another 'logo' and see if our monkey patch worked.
That worked! we're now displaying version 2 of our logo. Now that our logos are versioned, it would make much sense if we could add a link on the page to display the previous and next versions to the current version number. In our show view we can add the link after the code that displays the version number.
The if condition ensures that the link is only shown if the page has a previous version to show. We want to display the logo on the same page, but with a version parameter in the URL that has the value of the previous version of the page. Then in our logos controller show action we can check for the version parameter and, if we find it, go to the appropriate version of that page.
In our show action we use Vestal Versions' revert_to method to fetch the correct version of our logo if the version parameter has been passed. The revert_to method expects an integer value and our parameter will be a string so we need to cast it first.
Reloading the page we should now see our previous link
Now try clicking on that previous version link. It should take you back to our initial logo
When we visit an older version of a logo it would be nice to have a link back to the current version. We can do that by adding this code to our view.
And that's it, we now have a revision control kind of system with paperclip. Try uploading more images and try it out. If for some reason something did not work out for you, see the source of this tutorial on github and compare