Module: Shrine::UploadedFile::InstanceMethods

Included in:
Shrine::UploadedFile
Defined in:
lib/shrine/uploaded_file.rb

Constant Summary collapse

RFC2396_PARSER =
URI::RFC2396_Parser.new

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#idObject (readonly)

The location where the file was uploaded to the storage.



28
29
30
# File 'lib/shrine/uploaded_file.rb', line 28

def id
  @id
end

#metadataObject (readonly)

A hash of file metadata that was extracted during upload.



34
35
36
# File 'lib/shrine/uploaded_file.rb', line 34

def 
  @metadata
end

#storage_keyObject (readonly)

The identifier of the storage the file is uploaded to.



31
32
33
# File 'lib/shrine/uploaded_file.rb', line 31

def storage_key
  @storage_key
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?

Returns true if the other UploadedFile is uploaded to the same storage and it has the same #id.



228
229
230
231
232
# File 'lib/shrine/uploaded_file.rb', line 228

def ==(other)
  self.class       == other.class       &&
  self.id          == other.id          &&
  self.storage_key == other.storage_key
end

#[](key) ⇒ Object

Shorthand for accessing metadata values.



73
74
75
# File 'lib/shrine/uploaded_file.rb', line 73

def [](key)
  [key]
end

#as_jsonObject

Conform to ActiveSupport’s JSON interface.



217
218
219
# File 'lib/shrine/uploaded_file.rb', line 217

def as_json(*)
  data
end

#closeObject

Part of complying to the IO interface. It delegates to the internally opened IO object.



173
174
175
176
# File 'lib/shrine/uploaded_file.rb', line 173

def close
  io.close if opened?
  @io = nil
end

#dataObject

Returns serializable hash representation of the uploaded file.



222
223
224
# File 'lib/shrine/uploaded_file.rb', line 222

def data
  { "id" => id, "storage" => storage_key.to_s, "metadata" =>  }
end

#deleteObject

Calls ‘#delete` on the storage, which deletes the file from the storage.



201
202
203
# File 'lib/shrine/uploaded_file.rb', line 201

def delete
  storage.delete(id)
end

#downloadObject

Streams content into a newly created Tempfile and returns it.

If a block is given, the opened Tempfile object is yielded to the block, and at the end of the block it’s automatically closed and deleted. In this case the return value of the method is the block return value.

If no block is given, the opened Tempfile is returned.

uploaded_file.download
#=> #<File:/var/folders/.../20180302-33119-1h1vjbq.jpg>

# or

uploaded_file.download { |tempfile| tempfile.read } # tempfile is deleted


123
124
125
126
127
128
129
130
131
# File 'lib/shrine/uploaded_file.rb', line 123

def download(**)
  tempfile = Tempfile.new(["shrine", ".#{extension}"], binmode: true)
  stream(tempfile, **)
  tempfile.open

  block_given? ? yield(tempfile) : tempfile
ensure
  tempfile.close! if ($! || block_given?) && tempfile
end

#eof?Boolean

Part of complying to the IO interface. It delegates to the internally opened IO object.

Returns:

  • (Boolean)


161
162
163
# File 'lib/shrine/uploaded_file.rb', line 161

def eof?
  io.eof?
end

#exists?Boolean

Calls ‘#exists?` on the storage, which checks whether the file exists on the storage.

Returns:

  • (Boolean)


190
191
192
# File 'lib/shrine/uploaded_file.rb', line 190

def exists?
  storage.exists?(id)
end

#extensionObject

The extension derived from #id if present, otherwise it’s derived from #original_filename.



54
55
56
57
58
59
# File 'lib/shrine/uploaded_file.rb', line 54

def extension
  identifier = id =~ RFC2396_PARSER.make_regexp ? id.sub(/\?.+$/, "") : id # strip query params for shrine-url
  result = File.extname(identifier)[1..-1]
  result ||= File.extname(original_filename.to_s)[1..-1]
  result.downcase if result
end

#hashObject

Enables using UploadedFile objects as hash keys.



236
237
238
# File 'lib/shrine/uploaded_file.rb', line 236

def hash
  [id, storage_key].hash
end

#initialize(data) ⇒ Object

Initializes the uploaded file with the given data hash.



37
38
39
40
41
42
43
44
45
# File 'lib/shrine/uploaded_file.rb', line 37

def initialize(data)
  @id          = data[:id]              || data["id"]
  @storage_key = data[:storage]&.to_sym || data["storage"]&.to_sym
  @metadata    = data[:metadata]        || data["metadata"]        || {}

  fail Error, "#{data.inspect} isn't valid uploaded file data" unless @id && @storage_key

  storage # ensure storage is registered
end

#inspectObject

Returns simplified inspect output.



256
257
258
# File 'lib/shrine/uploaded_file.rb', line 256

def inspect
  "#<#{self.class.inspect} storage=#{storage_key.inspect} id=#{id.inspect} metadata=#{.inspect}>"
end

#mime_typeObject Also known as: content_type

The MIME type of the uploaded file.



67
68
69
# File 'lib/shrine/uploaded_file.rb', line 67

def mime_type
  ["mime_type"]
end

#openObject

Calls ‘#open` on the storage to open the uploaded file for reading. Most storages will return a lazy IO object which dynamically retrieves file content from the storage as the object is being read.

If a block is given, the opened IO object is yielded to the block, and at the end of the block it’s automatically closed. In this case the return value of the method is the block return value.

If no block is given, the opened IO object is returned.

uploaded_file.open #=> IO object returned by the storage
uploaded_file.read #=> "..."
uploaded_file.close

# or

uploaded_file.open { |io| io.read } # the IO is automatically closed


94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/shrine/uploaded_file.rb', line 94

def open(**)
  @io.close if @io
  @io = _open(**)

  return @io unless block_given?

  begin
    yield @io
  ensure
    close
    @io = nil
  end
end

#opened?Boolean

Returns whether the file has already been opened.

Returns:

  • (Boolean)


179
180
181
# File 'lib/shrine/uploaded_file.rb', line 179

def opened?
  !!@io
end

#original_filenameObject

The filename that was extracted from the uploaded file.



48
49
50
# File 'lib/shrine/uploaded_file.rb', line 48

def original_filename
  ["filename"]
end

#readObject

Part of complying to the IO interface. It delegates to the internally opened IO object.



155
156
157
# File 'lib/shrine/uploaded_file.rb', line 155

def read(*)
  io.read(*)
end

#replace(io) ⇒ Object

Uploads a new file to this file’s location and returns it.



195
196
197
# File 'lib/shrine/uploaded_file.rb', line 195

def replace(io, **)
  uploader.upload(io, **, location: id)
end

#rewindObject

Part of complying to the IO interface. It delegates to the internally opened IO object.



167
168
169
# File 'lib/shrine/uploaded_file.rb', line 167

def rewind
  io.rewind
end

#shrine_classObject

Returns the Shrine class that this file’s class is namespaced under.



251
252
253
# File 'lib/shrine/uploaded_file.rb', line 251

def shrine_class
  self.class.shrine_class
end

#sizeObject

The filesize of the uploaded file.



62
63
64
# File 'lib/shrine/uploaded_file.rb', line 62

def size
  (@io && @io.size) || (["size"] && Integer(["size"]))
end

#storageObject

Returns the storage that this file was uploaded to.



246
247
248
# File 'lib/shrine/uploaded_file.rb', line 246

def storage
  shrine_class.find_storage(storage_key)
end

#stream(destination) ⇒ Object

Streams uploaded file content into the specified destination. The destination object is given directly to ‘IO.copy_stream`, so it can be either a path on disk or an object that responds to `#write`.

If the uploaded file is already opened, it will be simply rewinded after streaming finishes. Otherwise the uploaded file is opened and then closed after streaming.

uploaded_file.stream(StringIO.new)
# or
uploaded_file.stream("/path/to/destination")


144
145
146
147
148
149
150
151
# File 'lib/shrine/uploaded_file.rb', line 144

def stream(destination, **)
  if opened?
    IO.copy_stream(io, destination)
    io.rewind
  else
    open(**) { |io| IO.copy_stream(io, destination) }
  end
end

#to_ioObject

Returns an opened IO object for the uploaded file.



206
207
208
# File 'lib/shrine/uploaded_file.rb', line 206

def to_io
  io
end

#to_jsonObject

Returns the data hash in the JSON format. Suitable for storing in a database column or passing to a background job.



212
213
214
# File 'lib/shrine/uploaded_file.rb', line 212

def to_json(*)
  data.to_json(*)
end

#uploaderObject

Returns an uploader object for the corresponding storage.



241
242
243
# File 'lib/shrine/uploaded_file.rb', line 241

def uploader
  shrine_class.new(storage_key)
end

#urlObject

Calls ‘#url` on the storage, forwarding any given URL options.



184
185
186
# File 'lib/shrine/uploaded_file.rb', line 184

def url(**)
  storage.url(id, **)
end