Use token instead of id in paperclip's path

I have been using paperclip in more then a couple of applications that I’m developing now, I really like it and it gives me the flexibility that I require.

caption id=”” align=”alignnone” width=”500” caption=”Url with Token example”Screen-shot-2010-12-17-at-12.57/caption

A couple of days ago, I wanted the path of the file to include a token instead of the id of  a user class.

This was my code before the change:

  has_attached_file :avatar,
    :styles =>
    {
      :tiny => "48x48>",
      :preview => "175x175>",
      :large => "300x300>",
      :huge => "500x500>"
    },
    :storage => :s3,
    :s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
    :path => ":class/:attachment/:id/:style.:extension",
    :bucket => 'lopsum',
    :default_url => "/images/photo01.jpg"

Notice that the path parameter includes the id of the user, this was not the requirement, because if this in an id parameter then the URL’s will be very easy to resolve and I of course don’t want that for user privacy.

I don’t want anyone to change the URL and get to the other profile images easily.

So, I needed a token which will be a random string for each user and I wanted that to be included in the path. This way, no one can tell the other paths in the system (it’s harder, a lot harder).

So, first thing first, I added this code to the user model:

  validates_presence_of :token

  protected
    def before_validation_on_create
      self.token = rand(36**10).to_s(36).upcase if self.new_record? and self.token.nil?
    end

I used a random code, you can of course use MD5 of the date or whatever you may want, just replace this code:

rand(36**10).to_s(36).upcase

Now that I have a token saved in the database I changed the image saving code to this:

  has_attached_file :avatar,
    :styles =>
    {
      :tiny => "48x48>",
      :preview => "175x175>",
      :large => "300x300>",
      :huge => "500x500>"
    },
    :storage => :s3,
    :s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
    :path => ":class/:attachment/:token/:style.:extension",
    :bucket => 'lopsum',
    :default_url => "/images/photo01.jpg"

This code did not work, the path only included the word :token but without the actual token from the database.

So, how can you fix this?

You need to add an initializer for paperclip.

You add a file called paperclip.rb into the config/initializers folder

You paste in this code:

Paperclip.interpolates :token do |attachment, style|
  attachment.instance.token
end

This will “tokenize” your user avatar path.

<img src="http://feeds.feedburner.com/~r/KensoDev-en/~4/JVaJ8nLUArk" height="1" width="1"/>
Thank you for your interest!

We will contact you as soon as possible.

Send us a message

Oops, something went wrong
Please try again or contact us by email at info@tikalk.com