# Copying attachment\_fu file uploads

**URL:** <https://www.ruby-forum.com/t/copying-attachment-fu-file-uploads/103759>\
**Category:** Rails\
**Created:** [May 10, 2007, 12:38am UTC](https://www.ruby-forum.com/t/copying-attachment-fu-file-uploads/103759 "2007-05-10T00:38:40Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![rob](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/838e76/32.png) [@rob](https://www.ruby-forum.com/u/rob)\
**Post date:** [May 10, 2007, 12:38am UTC](https://www.ruby-forum.com/t/copying-attachment-fu-file-uploads/103759/1 "2007-05-10T00:38:40Z")

</div>

I’m using attachment\_fu to provide file uploads/processing for a product  
class. I’d like to create a cloned version of a product with a copy of  
the initial versions image files. I don’t want the original version to  
share the cloned versions file but have new ones that are copies.

I could copy all images for the product and create new rows in the  
product\_images table (the one used by attachment\_fu) but this seems a  
bit inelegant, does anybody know a ‘better’ way or if attachment\_fu  
supports this functionality in some way ?

---

<div class="post-metadata">

**Author:** ![rob](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/838e76/32.png) [@rob](https://www.ruby-forum.com/u/rob)\
**Post date:** [May 10, 2007, 7:10am UTC](https://www.ruby-forum.com/t/copying-attachment-fu-file-uploads/103759/2 "2007-05-10T07:10:25Z")

</div>

> I could copy all images for the product and create new rows in the  
> product\_images table (the one used by attachment\_fu) but this seems a  
> bit inelegant, does anybody know a ‘better’ way or if attachment\_fu  
> supports this functionality in some way ?

Nope, it doesn’t support that. But if it did, it’d probably create  
new rows in your attachment table and copy over the attachments to the  
new copied records.

–  
Rick O.  
[http://lighthouseapp.com](http://lighthouseapp.com)  
[http://weblog.techno-weenie.net](http://weblog.techno-weenie.net)  
[http://mephistoblog.com](http://mephistoblog.com)

---

<div class="post-metadata">

**Author:** ![rob](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/838e76/32.png) [@rob](https://www.ruby-forum.com/u/rob)\
**Post date:** [May 10, 2007, 6:11pm UTC](https://www.ruby-forum.com/t/copying-attachment-fu-file-uploads/103759/3 "2007-05-10T18:11:45Z")

</div>

Rick O. wrote:

> Nope, it doesn’t support that. But if it did, it’d probably create  
> new rows in your attachment table and copy over the attachments to the  
> new copied records.

For reference, I ended up adding this to attachment\_fu.rb which I  
believe should work with all the backends for attachment\_fu :

```
  def create_clone

    c = self.clone

    self.thumbnails.each { |t|
      n = t.clone
      img = t.create_temp_file
      n.temp_path = img.path
      n.save_to_storage
      c.thumbnails<<n
    }

    img = self.create_temp_file
    c.temp_path = img.path
    c.save_to_storage

    c.save
    return c

  end
```

---

<div class="post-metadata">

**Author:** ![rob](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/838e76/32.png) [@rob](https://www.ruby-forum.com/u/rob)\
**Post date:** [September 24, 2007, 9:43am UTC](https://www.ruby-forum.com/t/copying-attachment-fu-file-uploads/103759/4 "2007-09-24T09:43:01Z")

</div>

Thanks for posting this! I added this in, with Rick’s suggested  
modifications, and it seems to do exactly what we were looking for.

Saved me about a day of figuring out how to implement the same thing  
myself.

–Bill

---

<div class="post-metadata">

**Author:** ![rob](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/838e76/32.png) [@rob](https://www.ruby-forum.com/u/rob)\
**Post date:** [May 10, 2007, 10:23pm UTC](https://www.ruby-forum.com/t/copying-attachment-fu-file-uploads/103759/5 "2007-05-10T22:23:32Z")

</div>

On 5/10/07, Rob L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> }
> 
> img = self.create_temp_file
> c.temp_path = img.path
> c.save_to_storage
> 
> c.save
> return c
> 
> end
> 
> ```

You should probably send ‘img’ to #temp\_path. Those are TempFile  
objects, and they will automatically be deleted when they’re garbage  
collected. So, you’ll lose the reference to them by passing img.path,  
and there’s a chance the file won’t be there when you go to save it.  
If you pass the TempFile instance, it won’t get garbage collected  
until after the rails request has completed.

–  
Rick O.  
[http://lighthouseapp.com](http://lighthouseapp.com)  
[http://weblog.techno-weenie.net](http://weblog.techno-weenie.net)  
[http://mephistoblog.com](http://mephistoblog.com)

---

<div class="post-metadata">

**Author:** ![rob](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/838e76/32.png) [@rob](https://www.ruby-forum.com/u/rob)\
**Post date:** [January 19, 2008, 1:00am UTC](https://www.ruby-forum.com/t/copying-attachment-fu-file-uploads/103759/6 "2008-01-19T01:00:42Z")

</div>

Sorry to be dim, but could someone post exactly the code which worked  
and where in the attachment\_fu.rb file it sits?

I’ve tried lots of different ways, and although the image file appears  
to save, I keep getting a weird IOError error on saving the object  
itself

Thanks in advance.

Terry

---

<div class="post-metadata">

**Author:** ![rob](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/838e76/32.png) [@rob](https://www.ruby-forum.com/u/rob)\
**Post date:** [February 4, 2008, 2:12pm UTC](https://www.ruby-forum.com/t/copying-attachment-fu-file-uploads/103759/7 "2008-02-04T14:12:47Z")

</div>

Er, sorry about that, the post needs a couple clarifications:

Christophe P. wrote:

> def clone\_with\_file  
> result = clone  
> result.temp\_path = create\_temp\_file  
> result  
> end

This is mostly intended to be private.

> def clone\_with\_files  
> self.class.transaction do  
> result = clone\_with\_file # I had forgotten to prune out extra args hereâ€¦  
> if attribute\_names.include?(‘parent\_id’)  
> result.thumbnails = thumbnails.map &:clone\_with\_file  
> end  
> result  
> end  
> end

This is essentially the method you’d call from outside. It will clone  
thumbnails if the table for your images features a standard parent\_id  
field, hinting at thumbnail setup (I could also have checked  
attachment\_fu\_options, but felt like pulling a quick trickâ€¦).

'HTH

–  
Christophe

---

<div class="post-metadata">

**Author:** ![rob](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/838e76/32.png) [@rob](https://www.ruby-forum.com/u/rob)\
**Post date:** [October 13, 2008, 2:07am UTC](https://www.ruby-forum.com/t/copying-attachment-fu-file-uploads/103759/8 "2008-10-13T02:07:41Z")

</div>

Faster version here:  
[http://www.williambharding.com/blog/rails/rails-faster-clonecopy-of-attachment\_fu-images/](http://www.williambharding.com/blog/rails/rails-faster-clonecopy-of-attachment_fu-images/)

Bill Harding wrote:

> Thanks for posting this! I added this in, with Rick’s suggested  
> modifications, and it seems to do exactly what we were looking for.
> 
> Saved me about a day of figuring out how to implement the same thing  
> myself.
> 
> –Bill

---

<div class="post-metadata">

**Author:** ![rob](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/838e76/32.png) [@rob](https://www.ruby-forum.com/u/rob)\
**Post date:** [February 4, 2008, 2:09pm UTC](https://www.ruby-forum.com/t/copying-attachment-fu-file-uploads/103759/9 "2008-02-04T14:09:59Z")

</div>

About the code you posted:

You’re better off leaving the save\_to\_storage code out, as it will get  
called automatically after save, AND if called before that you’ll get  
weird file names due to zero ID before save. So your file will get  
saved to a first name that is incorrect, and a second one that is  
correct, post-DB-save.

The code for cloning thumbnails and the main image is redundant, too,  
and it won’t work on images with no thumbnail setup. Here’s how I went  
about it, as a suggestion (I stripped the custom code I added to update  
the reference to the parent model, which was besides the point here):

def clone\_with\_file  
result = clone  
result.temp\_path = create\_temp\_file  
result  
end

def clone\_with\_files  
self.class.transaction do  
result = clone\_with\_file(new\_draft, strict)  
if attribute\_names.include?(‘parent\_id’)  
result.thumbnails = thumbnails.map &:clone\_with\_file  
end  
result  
end  
end

Just a thoughtâ€¦
