55

I am trying to display the filename of a Carrierwave attachment in a Rails erb template. The following does not work:

<%= @page.form.filename %>

This seems in line with the documentation. Is some additional step needed?

My page model looks like this:

class Page < ActiveRecord::Base

  mount_uploader :form, FormUploader

end

The form uploader looks like this:

class FormUploader < CarrierWave::Uploader::Base

  storage :file

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_white_list
    %w(pdf)
  end

end
Deepak Mahakale
  • 22,834
  • 10
  • 68
  • 88
Chris Alley
  • 3,015
  • 2
  • 21
  • 31

10 Answers10

86

I have been able to get the filename via the file internal parameter:

<%= @page.form.file.filename %>
kikito
  • 51,734
  • 32
  • 149
  • 189
81

The documentation you're looking at is the sanitized file, it's what it uses for actually storing a file. The part you're looking for is FormUploader, which is an Uploader, and part of http://rubydoc.info/gems/carrierwave/0.5.2/CarrierWave/Uploader

If you want to get the file name, you could either read it from the database column directly, or use File.basename(@page.form.path) to extract it easily.

Zachary Anker
  • 4,500
  • 21
  • 19
  • 3
    you should use path instead of url, using url with aws or another cloud provider will include querystrings – Orlando Jun 28 '12 at 18:37
  • Only if you're using signed URLs, I've corrected it to paths though. – Zachary Anker Jun 28 '12 at 19:53
  • 1
    Just thought I would say, that if you are using a mounted uploader named image in the images table you would get to the basename like this Image.first.image.file.basename it tripped me up a little while first investigating this. I was trying to use Image.first.image.basename which is not valid. – bloveless Jul 10 '12 at 23:10
  • Not sure how I accidentally downvoted this answer, but if @Zachary Anker would edit it I could upvote it. – Jamon Holmgren Jul 20 '12 at 04:20
  • 2
    Hmm why is it better than Kikito answer `@page.form.file.filename` ? – Cyril Duchon-Doris May 08 '15 at 16:09
17

The Carrierwave docs might be a bit off, but recommended way seems to be:

@page.form.file.identifier
Deepak Mahakale
  • 22,834
  • 10
  • 68
  • 88
epylinkn
  • 1,128
  • 12
  • 16
9

@adamonduty's solution is great. Another solution I used before, just create a method on the model:

def name
  file.path.split("/").last
end
Deepak Mahakale
  • 22,834
  • 10
  • 68
  • 88
omarvelous
  • 2,774
  • 14
  • 18
6

You're right @epylinkn. Documentation points towards using:

@page.form.file.identifier

But when I use that, I always get nil (just as @Cheng commented).

I then inspected my objects methods (@page.form.file.methods.inspect), and found the following to work:

@page.form.file_identifier
Deepak Mahakale
  • 22,834
  • 10
  • 68
  • 88
skplunkerin
  • 2,123
  • 5
  • 28
  • 40
  • 1
    yes, the working method is `xxx_identifer`. underscore + url, underscore + identifier, etc... is the syntax form adopted for the methods – Jerome Dec 28 '16 at 14:28
6

In your model's associated uploader class, define a filename method.

def filename
  File.basename(path)
end

You can then call

model_instance.file.filename

Works as of CarrierWave 1.1.0. This is a succinct restatement/amalgamation of kikito and Chris Alley's responses above.

Gerry
  • 10,337
  • 3
  • 31
  • 40
Solomons_Ecclesiastes
  • 2,039
  • 3
  • 14
  • 17
4

If you're using ActiveRecord, you can directly access the field named form in two ways:

def my_method
  self[:form]
end

or

def my_method
  form_before_type_cast
end

The second method is read-only.

adamlamar
  • 4,629
  • 2
  • 27
  • 22
  • The other solutions fail when there is no uploaded file. `user['avatar']` will return the filename or `nil`. – psmith Aug 24 '16 at 02:06
3

CarrierWave::SanitizedFile has a private original_filename method containing the filename of the uploaded file. (docs: http://rdoc.info/github/jnicklas/carrierwave/master/CarrierWave/SanitizedFile:original_filename)

After reading through this thread from the CarrierWave mailing list, none seemed to fit my needs. With something like

class Upload < ActiveRecord::Base
  mount_uploader :file, FileUploader
  # ...

I heavily modify the :file column value from the original filename. Due to this I decided to track the original filename in a separate column from the one bound to CarrierWave. In my FileUploader I simply added a reader that wraps the private original_filename method:

def original_file
  original_filename
end

I then added a before_create event to the Upload class (my Upload records are never modified, so a before_create is acceptable for my needs)

before_create do
  self.original_file = self.file.original_file
end
Nightfirecat
  • 11,432
  • 6
  • 35
  • 51
deefour
  • 34,974
  • 7
  • 97
  • 90
2

I'm assuming you've got models like this?

class Page
  mount_uploader :form, FormUploader
end

If so you should be able to call:

@page.form.url
@page.form.filename

Are you sure you've uploaded/attached the file correctly? What do you see when you inspect @page.form? Remember, the attachment will not be saved until you've fully processed the upload.

Winfield
  • 18,985
  • 3
  • 52
  • 65
  • The attachment is saving fine. I've updated my question with the model and uploader code. Don't worry, zanker's answer fixed it. – Chris Alley Feb 28 '11 at 20:32
1

This is my solution:

  before_save :update_file_attributes


  def update_file_attributes
    if file.present? && file_changed? 
      self.content_type = file.file.content_type
      self.file_size = file.file.size
      self.file_name = read_attribute(:file)
    end
  end
why
  • 23,923
  • 29
  • 97
  • 142