Forced clip to rename files when changing user interpolation

I use Paperclip to manage uploaded images for a specific model in Rails 3. This belongs_to model belongs_to different model. I want my image path to reflect this relationship, so for this I created custom interpolation.

The problem is that I also want to be able to edit the name of belongs_to objects, and I would like Paperclip to rename the files accordingly.

Here is a simple example:

 class Make < ActiveRecord:Base attr_accessible :name has_many :models end class Model < ActiveRecord:Base attr_accessible :img, :make, :name belongs_to :make has_attached_file :img, :style => { :thumb => "100x100" }, :path => "/cars/:make_name/:name/:style/:hash.png", :hash_secret => "blabla" Paperclip.interpolates :make_name do |attachment, style| attachment.instance.make.name end Paperclip.interpolates :name do |attachment, style| attachment.instance.name end end 

So let's say I create make Chevrolet and Model Camaro , my image path will be /cars/chevrolet/camaro/thumb/my_hash.png

If I decide to change the Chevrolet record name to Chevy , Rails will try to find the image in /cars/chevy/camaro/thumb/my_hash.png , but since the image was not renamed, it was not found.

How to get Paperclip to update all image paths when renaming a record?

Thanks!

+4
source share
2 answers

A more reliable file path might use the make identifier instead of the name. Ie, /cars/:make_id/:name/:style/:hash.png will continue to work when the name is changed.

+2
source

I have found several ways. Let me explain.

At first, I think this problem has arisen for many of us, and it would be wise to make it a standard clip function.

There are two solutions:

  • Move / rename files to the new logic: clean, use less processor (without image processing), but in any case (depending on interpolation, local storage and S3 storage, etc.) and risky (if there is a production server)

    Here are the answers when people decided to move the files:

  • Create a new one and destroy the first one. This is the one I chose.

So, first you need to intercept when the file logic is moving. In my case, I have a before_save :generate_slug method that restores the user's slug if it has changed. Here I have to put the clip regeneration logic, since my interpolation contains slug .

The only thing I needed to do was add http://localhost:3000 to user.avatar.url because it returns the local path to the file when it is local and not the URI that is used for URI.parse . I use S3 in production, so in this case it works.

Here is my generate_slug method:

  def generate_slug if !(self.slug == self.fullname.parameterize) # Changed if self.avatar.exists? # There actually is an avatar to move if self.avatar.url.include? "http" avatar_url = self.avatar.url else # means url is local path ==> needs to add localhost to have a correct URI avatar_url = 'http://localhost:3000' + self.avatar.url end self.avatar.clear # To remove the former file end self.slug = self.fullname.parameterize if !avatar_url.blank? self.avatar = URI.parse(avatar_url) end end end 

Hope this helps, wish there is a cleaner solution!

0
source

Source: https://habr.com/ru/post/1440671/


All Articles