/
file.cr
131 lines (110 loc) · 3.87 KB
/
file.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
module Marten
module DB
module Field
# Represents a file field's value.
#
# Instances of this class give access to the properties of a file manipulated by a `file` field. They allow to
# read a file's content, and to attach new files to model records.
class File < Base
class File
@committed = true
@file : ::File | HTTP::UploadedFile | Nil = nil
@record : Model? = nil
# :nodoc:
getter file
# Returns the name of the file or `nil` if no file is set.
getter name
# :nodoc:
getter record
# :nodoc:
setter committed
# Allows to associate a new file to the field.
setter file
# :nodoc:
setter record
def initialize(@field : Field::File, @name : ::String? = nil)
end
# Returns `true` if a file is attached to the field and record.
def attached?
!@name.nil?
end
# Returns `true` if the file is committed to the underlying storage.
def committed?
@committed
end
# Deletes the associated filfe from the storage.
#
# A `Marten::DB::Errors::UnexpectedFieldValue` error is raised if no file is associated with this object.
# Optionally, a `save` boolean can be set to force the associated record to be saved along the way.
def delete(save = false) : Nil
with_ensured_file do
@field.storage.delete(name!)
self.file = nil
self.name = nil
self.committed = false
record!.save if save
end
end
# Returns a `IO` object allowing to interact with the file's content.
#
# A `Marten::DB::Errors::UnexpectedFieldValue` error is raised if no file is associated with this object.
def open : IO
with_ensured_file do
if !committed?
case f = file
when ::File
f
when HTTP::UploadedFile
f.io
end.not_nil!
else
@field.storage.open(name!)
end
end
end
# Allows to save a new file to the underlying storage.
#
# A `filepath` string and a `content` IO must be specified. Optionally, a `save` boolean can be set to force
# the associated record to be saved along the way.
def save(filepath : ::String, content : IO, save = false) : Nil
self.name = @field.storage.save(field.sanitize_filename(filepath), content)
self.committed = true
record!.save if save
end
# Returns the `size` of the file.
#
# A `Marten::DB::Errors::UnexpectedFieldValue` error is raised if no file is associated with this object.
def size : Int64
with_ensured_file do
if !committed?
file.not_nil!.size.try(&.to_i64).not_nil!
else
@field.storage.size(name!)
end
end
end
# Returns the URL of the file.
#
# A `Marten::DB::Errors::UnexpectedFieldValue` error is raised if no file is associated with this object.
def url : ::String
with_ensured_file do
@field.storage.url(name.not_nil!)
end
end
private getter field
private setter name
private def name!
name.not_nil!
end
private def record!
record.not_nil!
end
private def with_ensured_file(&)
raise Errors::UnexpectedFieldValue.new("No file available") if name.nil?
yield
end
end
end
end
end
end