Setting Custom URL and Paths for Paperlip Attachments in Rails

PaperClip is an awesome file attachment library for Active Record built by thoughtbot. It helps you get started with uploads in rails in less than a few minutes.

By default the path and location of storing file by PaperClip are

:url => "/system/:attachment/:id/:style/:basename.:extension"

:path => ":rails_root/public/system/:attachment/:id/:style/:basename.:extension"

which appears to be like

Rails.root/public/system/user/0/0/sample.pdf

When we need to change this path, by default it can be changed only to

Rails.root/public/:attachment/:id/:basename.:extension

but what if we need to change it to look more like our routes

Rails.root/public/companies/company_id/groups/group_id/projects/project_id/my_file_name.with_extension

this is feature which doesn’t work by default for paperclip. But there is a little hack available for this like mentioned here at stackoverflow.

Add an initializer paperclip_default_url_fix.rb

paperclip_default_url_fix.rb
1
2
3
4
5
6
7
8
9
10
11
12
module Paperclip
  module Interpolations
    def self.interpolate pattern, *args
      pattern = args.first.instance.send(pattern) if pattern.kind_of? Symbol
      all.reverse.inject( pattern.dup ) do |result, tag|
        result.gsub(/:#{tag}/) do |match|
          send( tag, *args )
        end
      end
    end
  end
end    

Now we can create any path and url to save and access attachment.

Project.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Project < ActiveRecord::Base

  has_attached_file :attachment,
  :url => :set_attachment_url,
  :path => :set_attachment_path

  def set_attachment_url
    "/companies/#{self.company_id}/groups/#{self.group_id}/projects/#{self.id}/#{attachment_file_name}"
  end

  def set_attachment_path
      "#{Rails.root}/public/companies/#{self.company_id}/groups/#{self.group_id}/projects/#{self.id}/#{attachment_file_name}"
  end

end

Cheers :)

Comments