Making Dynamic Paths for Paperclip

December 03, 2010

  • Rails
  • Ruby
  • ruby-on-rails
  • dynamic-path-paperclip
  • paperclip
  • path
  • ruby-gems

If you ever want to upload and save files in your rails app, you can use this gem Paperclip.

According to the owner of this gem

Paperclip is intended as an easy file attachment library for ActiveRecord. The intent behind it was to keep setup as easy as possible and to treat files as much like other attributes as possible. This means they aren’t saved to their final locations on disk, nor are they deleted if set to nil, until ActiveRecord::Base#save is called. It manages validations based on size and presence, if required. It can transform its assigned image into thumbnails if needed, and the prerequisites are as simple as installing ImageMagick (which, for most modern Unix-based systems, is as easy as installing the right packages). Attached files are saved to the filesystem and referenced in the browser by an easily understandable specification, which has sensible and useful defaults.

This gem proves to be very helpful in attaching and uploading files to your rails-app. You can read the implementation guide on the site. What I am basically focussing on is how can we create dynamic path for storing the files uploaded using Paperclip.

Earlier my application had these settings

has_attached_file :user_image
                 :url => "../assets/users/#{self.name}_:basename_:id" + ".:extension",
                 :path => ":rails_root/public/assets/users/#{self.name}_:basename_:id" + ".:extension"

This would save the file in the RAILS_ROOT/public/assets/users/ directory. But I wanted to store it in RAILS_ROOT/public/assets/users/#{user_id} directory. i.e. create a separate directory for each and every user in our app.

So, I tried to use this:

has_attached_file :user_image
                 :url => "../assets/users/#{self.user.id.to_s}/#{self.name}_:basename_:id" + ".:extension",
                 :path => ":rails_root/public/assets/users/#{self.user.id.to_s}/#{self.name}_:basename_:id" + ".:extension"

But it didn’t work. Referring many other tutorials didn’t seem to work help in my case. After some time I stumbled upon the Paperclip::Interpolations module and came across the methods basename, id, extension etc. These methods provide for the tags used in the path and url of paperclip.

So I ended up making a helper in config/initializers directory. The ultimate goal was to, overwrite the Paperclip::Interpolations module and add a method user_id in it, which will retrun us the user id. Here’s the code for the helper.

module Paperclip
    module Interpolations
        def user_id attachment, style_name
            attachment.instance.user_id
        end
    end
end

And now we use this

has_attached_file :user_image
                 :url => "../assets/users/:user_id/#{self.name}_:basename_:id" + ".:extension",
                 :path => ":rails_root/public/assets/users/:user_id/#{self.name}_:basename_:id" + ".:extension"

Now it stores the file in RAILS_ROOT/assets/users/1/ directory. And that’s what we wanted to do. Thanks. Have a great day. :D


LOCATION

Mumbai, Maharashtra, India

AROUND THE WEB

Copyright © 2021