title: CarrierWave: Create the same, unique filename for all versioned files
body: <p>Before I go into detail I'll get right to the point: has anyone figured out a way to get Carrierwave to save files with their names as a timestamp or any arbitrary string that is unique to each file?</p>
  
  <p>By default Carrierwave saves each file and its alternate versions in its own directory (named after the model ID number). I'm not a fan of this because instead of one directory with 1,000, for the sake of using a large round number, files (in my case pictures) in it we get one directory with 1,000 subdirectories each with one or two files. Yuck.</p>
  
  <p>Now, when you override your Uploader's <code>store_dir</code> method to be something like the following:</p>
  
  <pre><code>def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}"
  end
  </code></pre>
  
  <p>you end up with the exact behavior that I want. All the files (pictures) go into one big happy folder. No more subfolders that stick around when the object gets deleted.</p>
  
  <p>There's only one problem. File collisions. If you upload delicious_cake.jpg twice the second one will overwrite the first even if they are two different pictures of delicious cake! That's clearly why the <code>store_dir</code> method has the extra <code>/#{model.id}</code> tacked on the end of the value it returns.</p>
  
  <p>So, what to do? After reading around a bit I discovered that in the generated uploader file there is an apparent solution commented out.</p>
  
  <pre><code># Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  # def filename
  #   "something.jpg" if original_filename
  # end
  </code></pre>
  
  <p>After a little bit of searching I found someone who had done the following</p>
  
  <pre><code>def filename
    @name ||= "#{secure_token}.#{file.extension}" if original_filename
  end
  </code></pre>
  
  <p>This got me thinking, why not just do this</p>
  
  <pre><code>def filename
    @name ||= "#{(Time.now.to_i.to_s + Time.now.usec.to_s).ljust(16, '0')}#{File.extname(original_filename)}"
  end
  </code></pre>
  
  <p>That's when things got horribly broken. The problem with this is that <code>filename</code> apparently gets called for each version of the file so we end up with file names like 1312335603175322.jpg and thumb_1312335603195323.jpg. Notice the slight difference? Each file name is based on the time when <code>filename</code> was called for that particular version. That won't do at all.</p>
  
  <p>I next tired using <code>model.created_at</code> for the basis of the timestamp. Only one problem, that returns nil for the first version since it hasn't been put in the database yet.</p>
  
  <p>After some further thinking I decided to try the following in my pictures controller.</p>
  
  <pre><code>def create
    if params[:picture] and params[:picture][:image]
      params[:picture][:image].original_filename = "#{(Time.now.to_i.to_s + Time.now.usec.to_s).ljust(16, '0')}#{File.extname(params[:picture][:image].original_filename)}"
    end
    ...
  </code></pre>
  
  <p>This overrides the original_filename property before Carrierwave even gets to it making it be a timestamp. It does exactly what I want. The original version of the file ends up with a name like 1312332906940106.jpg and the thumbnail version (or any other version) ends up with a name like thumb_1312332906940106.jpg.</p>
  
  <p>But, this seems like an awful hack. This should be part of the model, or better yet part of the uploader mounted onto the model.</p>
  
  <p>So, my question is, is there a better way to achieve this? Did I miss something crucial with Carrierwave that makes this easy? Is there a not so obvious but cleaner way of going about this? Working code is good, but working code that doesn't smell bad is better.</p>