refile 0.5.5 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/refile.rb +252 -27
- data/lib/refile/app.rb +55 -14
- data/lib/refile/attacher.rb +39 -40
- data/lib/refile/attachment.rb +28 -13
- data/lib/refile/attachment/active_record.rb +90 -1
- data/lib/refile/attachment_definition.rb +47 -0
- data/lib/refile/backend/s3.rb +1 -147
- data/lib/refile/backend_macros.rb +13 -5
- data/lib/refile/custom_logger.rb +3 -1
- data/lib/refile/file.rb +9 -0
- data/lib/refile/image_processing.rb +1 -143
- data/lib/refile/rails.rb +30 -0
- data/lib/refile/rails/attachment_helper.rb +27 -16
- data/lib/refile/signature.rb +5 -0
- data/lib/refile/simple_form.rb +17 -0
- data/lib/refile/version.rb +1 -1
- data/spec/refile/active_record_helper.rb +11 -0
- data/spec/refile/app_spec.rb +197 -20
- data/spec/refile/attachment/active_record_spec.rb +298 -1
- data/spec/refile/attachment_helper_spec.rb +39 -0
- data/spec/refile/attachment_spec.rb +53 -5
- data/spec/refile/backend_examples.rb +13 -2
- data/spec/refile/backend_macros_spec.rb +27 -6
- data/spec/refile/custom_logger_spec.rb +2 -3
- data/spec/refile/features/direct_upload_spec.rb +18 -0
- data/spec/refile/features/multiple_upload_spec.rb +122 -0
- data/spec/refile/features/normal_upload_spec.rb +5 -3
- data/spec/refile/features/presigned_upload_spec.rb +4 -0
- data/spec/refile/features/simple_form_spec.rb +8 -0
- data/spec/refile/fixtures/monkey.txt +1 -0
- data/spec/refile/fixtures/world.txt +1 -0
- data/spec/refile/spec_helper.rb +21 -11
- data/spec/refile_spec.rb +253 -24
- metadata +12 -303
- data/.gitignore +0 -27
- data/.rspec +0 -2
- data/.rubocop.yml +0 -68
- data/.travis.yml +0 -21
- data/.yardopts +0 -1
- data/CONTRIBUTING.md +0 -33
- data/Gemfile +0 -3
- data/History.md +0 -96
- data/LICENSE.txt +0 -22
- data/README.md +0 -651
- data/Rakefile +0 -19
- data/app/assets/javascripts/refile.js +0 -63
- data/config.ru +0 -8
- data/config/locales/en.yml +0 -8
- data/config/routes.rb +0 -5
- data/refile.gemspec +0 -42
- data/spec/refile/backend/s3_spec.rb +0 -11
- data/spec/refile/test_app.rb +0 -65
- data/spec/refile/test_app/app/assets/javascripts/application.js +0 -42
- data/spec/refile/test_app/app/controllers/application_controller.rb +0 -2
- data/spec/refile/test_app/app/controllers/direct_posts_controller.rb +0 -15
- data/spec/refile/test_app/app/controllers/home_controller.rb +0 -4
- data/spec/refile/test_app/app/controllers/normal_posts_controller.rb +0 -48
- data/spec/refile/test_app/app/controllers/presigned_posts_controller.rb +0 -31
- data/spec/refile/test_app/app/models/post.rb +0 -5
- data/spec/refile/test_app/app/views/direct_posts/new.html.erb +0 -20
- data/spec/refile/test_app/app/views/home/index.html.erb +0 -1
- data/spec/refile/test_app/app/views/layouts/application.html.erb +0 -14
- data/spec/refile/test_app/app/views/normal_posts/_form.html.erb +0 -28
- data/spec/refile/test_app/app/views/normal_posts/edit.html.erb +0 -1
- data/spec/refile/test_app/app/views/normal_posts/index.html +0 -5
- data/spec/refile/test_app/app/views/normal_posts/new.html.erb +0 -1
- data/spec/refile/test_app/app/views/normal_posts/show.html.erb +0 -19
- data/spec/refile/test_app/app/views/presigned_posts/new.html.erb +0 -16
- data/spec/refile/test_app/config/database.yml +0 -7
- data/spec/refile/test_app/config/routes.rb +0 -17
- data/spec/refile/test_app/public/favicon.ico +0 -0
data/lib/refile/attacher.rb
CHANGED
@@ -1,27 +1,32 @@
|
|
1
1
|
module Refile
|
2
2
|
# @api private
|
3
3
|
class Attacher
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :definition, :record, :errors
|
5
5
|
attr_accessor :remove
|
6
6
|
|
7
7
|
Presence = ->(val) { val if val != "" }
|
8
8
|
|
9
|
-
def initialize(
|
9
|
+
def initialize(definition, record)
|
10
|
+
@definition = definition
|
10
11
|
@record = record
|
11
|
-
@name = name
|
12
|
-
@raise_errors = raise_errors
|
13
|
-
@cache = Refile.backends.fetch(cache.to_s)
|
14
|
-
@store = Refile.backends.fetch(store.to_s)
|
15
|
-
@type = type
|
16
|
-
@valid_extensions = [extension].flatten if extension
|
17
|
-
@valid_content_types = [content_type].flatten if content_type
|
18
|
-
@valid_content_types ||= Refile.types.fetch(type).content_type if type
|
19
12
|
@errors = []
|
20
13
|
@metadata = {}
|
21
14
|
end
|
22
15
|
|
16
|
+
def name
|
17
|
+
@definition.name
|
18
|
+
end
|
19
|
+
|
20
|
+
def cache
|
21
|
+
@definition.cache
|
22
|
+
end
|
23
|
+
|
24
|
+
def store
|
25
|
+
@definition.store
|
26
|
+
end
|
27
|
+
|
23
28
|
def id
|
24
|
-
Presence[read(:id)]
|
29
|
+
Presence[read(:id, true)]
|
25
30
|
end
|
26
31
|
|
27
32
|
def size
|
@@ -66,7 +71,7 @@ module Refile
|
|
66
71
|
end
|
67
72
|
|
68
73
|
def set(value)
|
69
|
-
if value.is_a?(String)
|
74
|
+
if value.is_a?(String) or value.is_a?(Hash)
|
70
75
|
retrieve!(value)
|
71
76
|
else
|
72
77
|
cache!(value)
|
@@ -74,9 +79,12 @@ module Refile
|
|
74
79
|
end
|
75
80
|
|
76
81
|
def retrieve!(value)
|
77
|
-
|
82
|
+
if value.is_a?(String)
|
83
|
+
@metadata = Refile.parse_json(value, symbolize_names: true) || {}
|
84
|
+
elsif value.is_a?(Hash)
|
85
|
+
@metadata = value
|
86
|
+
end
|
78
87
|
write_metadata if cache_id
|
79
|
-
rescue JSON::ParserError
|
80
88
|
end
|
81
89
|
|
82
90
|
def cache!(uploadable)
|
@@ -88,7 +96,7 @@ module Refile
|
|
88
96
|
if valid?
|
89
97
|
@metadata[:id] = cache.upload(uploadable).id
|
90
98
|
write_metadata
|
91
|
-
elsif @raise_errors
|
99
|
+
elsif @definition.raise_errors?
|
92
100
|
raise Refile::Invalid, @errors.join(", ")
|
93
101
|
end
|
94
102
|
end
|
@@ -98,29 +106,30 @@ module Refile
|
|
98
106
|
response = RestClient::Request.new(method: :get, url: url, raw_response: true).execute
|
99
107
|
@metadata = {
|
100
108
|
size: response.file.size,
|
101
|
-
filename:
|
109
|
+
filename: URI.parse(url).path.split("/").last,
|
102
110
|
content_type: response.headers[:content_type]
|
103
111
|
}
|
104
112
|
if valid?
|
113
|
+
response.file.open if response.file.closed? # https://github.com/refile/refile/pull/210
|
105
114
|
@metadata[:id] = cache.upload(response.file).id
|
106
115
|
write_metadata
|
107
|
-
elsif @raise_errors
|
116
|
+
elsif @definition.raise_errors?
|
108
117
|
raise Refile::Invalid, @errors.join(", ")
|
109
118
|
end
|
110
119
|
end
|
111
120
|
rescue RestClient::Exception
|
112
121
|
@errors = [:download_failed]
|
113
|
-
raise if @raise_errors
|
122
|
+
raise if @definition.raise_errors?
|
114
123
|
end
|
115
124
|
|
116
125
|
def store!
|
117
126
|
if remove?
|
118
127
|
delete!
|
119
|
-
write(:id, nil)
|
128
|
+
write(:id, nil, true)
|
120
129
|
elsif cache_id
|
121
130
|
file = store.upload(get)
|
122
131
|
delete!
|
123
|
-
write(:id, file.id)
|
132
|
+
write(:id, file.id, true)
|
124
133
|
end
|
125
134
|
write_metadata
|
126
135
|
@metadata = {}
|
@@ -132,14 +141,6 @@ module Refile
|
|
132
141
|
@metadata = {}
|
133
142
|
end
|
134
143
|
|
135
|
-
def accept
|
136
|
-
if valid_content_types
|
137
|
-
valid_content_types.join(",")
|
138
|
-
elsif valid_extensions
|
139
|
-
valid_extensions.map { |e| ".#{e}" }.join(",")
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
144
|
def remove?
|
144
145
|
remove and remove != "" and remove !~ /\A0|false$\z/
|
145
146
|
end
|
@@ -148,29 +149,27 @@ module Refile
|
|
148
149
|
not @metadata.empty?
|
149
150
|
end
|
150
151
|
|
151
|
-
def valid?
|
152
|
-
@errors = []
|
153
|
-
@errors << :invalid_extension if valid_extensions and not valid_extensions.include?(extension)
|
154
|
-
@errors << :invalid_content_type if valid_content_types and not valid_content_types.include?(content_type)
|
155
|
-
@errors << :too_large if cache.max_size and size and size >= cache.max_size
|
156
|
-
@errors.empty?
|
157
|
-
end
|
158
|
-
|
159
152
|
def data
|
160
153
|
@metadata if valid?
|
161
154
|
end
|
162
155
|
|
156
|
+
def valid?
|
157
|
+
@errors = @definition.validate(self)
|
158
|
+
@errors.empty?
|
159
|
+
end
|
160
|
+
|
163
161
|
private
|
164
162
|
|
165
|
-
def read(column)
|
163
|
+
def read(column, strict = false)
|
166
164
|
m = "#{name}_#{column}"
|
167
|
-
value ||= record.send(m) if record.respond_to?(m)
|
165
|
+
value ||= record.send(m) if strict or record.respond_to?(m)
|
168
166
|
value
|
169
167
|
end
|
170
168
|
|
171
|
-
def write(column, value)
|
169
|
+
def write(column, value, strict = false)
|
170
|
+
return if record.frozen?
|
172
171
|
m = "#{name}_#{column}="
|
173
|
-
record.send(m, value) if record.respond_to?(m)
|
172
|
+
record.send(m, value) if strict or record.respond_to?(m)
|
174
173
|
end
|
175
174
|
|
176
175
|
def write_metadata
|
data/lib/refile/attachment.rb
CHANGED
@@ -17,10 +17,11 @@ module Refile
|
|
17
17
|
# - `remove_image=`
|
18
18
|
# - `remote_image_url`
|
19
19
|
# - `remote_image_url=`
|
20
|
+
# - `image_url`
|
20
21
|
#
|
21
22
|
# @example
|
22
23
|
# class User
|
23
|
-
#
|
24
|
+
# extend Refile::Attachment
|
24
25
|
#
|
25
26
|
# attachment :image
|
26
27
|
# attr_accessor :image_id
|
@@ -34,24 +35,30 @@ module Refile
|
|
34
35
|
# @param [String, Array<String>, nil] extension Limit the uploaded file to the given extension or list of extensions
|
35
36
|
# @param [String, Array<String>, nil] content_type Limit the uploaded file to the given content type or list of content types
|
36
37
|
# @return [void]
|
37
|
-
# @ignore
|
38
|
-
# rubocop:disable Metrics/MethodLength
|
39
38
|
def attachment(name, cache: :cache, store: :store, raise_errors: true, type: nil, extension: nil, content_type: nil)
|
39
|
+
definition = AttachmentDefinition.new(name,
|
40
|
+
cache: cache,
|
41
|
+
store: store,
|
42
|
+
raise_errors: raise_errors,
|
43
|
+
type: type,
|
44
|
+
extension: extension,
|
45
|
+
content_type: content_type
|
46
|
+
)
|
47
|
+
|
48
|
+
define_singleton_method :"#{name}_attachment_definition" do
|
49
|
+
definition
|
50
|
+
end
|
51
|
+
|
40
52
|
mod = Module.new do
|
41
53
|
attacher = :"#{name}_attacher"
|
42
54
|
|
55
|
+
define_method :"#{name}_attachment_definition" do
|
56
|
+
definition
|
57
|
+
end
|
58
|
+
|
43
59
|
define_method attacher do
|
44
60
|
ivar = :"@#{attacher}"
|
45
|
-
instance_variable_get(ivar) or
|
46
|
-
instance_variable_set(ivar, Attacher.new(self, name,
|
47
|
-
cache: cache,
|
48
|
-
store: store,
|
49
|
-
raise_errors: raise_errors,
|
50
|
-
type: type,
|
51
|
-
extension: extension,
|
52
|
-
content_type: content_type
|
53
|
-
))
|
54
|
-
end
|
61
|
+
instance_variable_get(ivar) or instance_variable_set(ivar, Attacher.new(definition, self))
|
55
62
|
end
|
56
63
|
|
57
64
|
define_method "#{name}=" do |value|
|
@@ -77,6 +84,14 @@ module Refile
|
|
77
84
|
define_method "remote_#{name}_url" do
|
78
85
|
end
|
79
86
|
|
87
|
+
define_method "#{name}_url" do |*args|
|
88
|
+
Refile.attachment_url(self, name, *args)
|
89
|
+
end
|
90
|
+
|
91
|
+
define_method "#{name}_data" do
|
92
|
+
send(attacher).data
|
93
|
+
end
|
94
|
+
|
80
95
|
define_singleton_method("to_s") { "Refile::Attachment(#{name})" }
|
81
96
|
define_singleton_method("inspect") { "Refile::Attachment(#{name})" }
|
82
97
|
end
|
@@ -5,6 +5,7 @@ module Refile
|
|
5
5
|
|
6
6
|
# Attachment method which hooks into ActiveRecord models
|
7
7
|
#
|
8
|
+
# @return [void]
|
8
9
|
# @see Refile::Attachment#attachment
|
9
10
|
def attachment(name, raise_errors: false, **options)
|
10
11
|
super
|
@@ -15,10 +16,27 @@ module Refile
|
|
15
16
|
if send(attacher).present?
|
16
17
|
send(attacher).valid?
|
17
18
|
errors = send(attacher).errors
|
18
|
-
|
19
|
+
errors.each do |error|
|
20
|
+
self.errors.add(name, error)
|
21
|
+
end
|
19
22
|
end
|
20
23
|
end
|
21
24
|
|
25
|
+
define_method "#{name}=" do |value|
|
26
|
+
send("#{name}_id_will_change!")
|
27
|
+
super(value)
|
28
|
+
end
|
29
|
+
|
30
|
+
define_method "remove_#{name}=" do |value|
|
31
|
+
send("#{name}_id_will_change!")
|
32
|
+
super(value)
|
33
|
+
end
|
34
|
+
|
35
|
+
define_method "remote_#{name}_url=" do |value|
|
36
|
+
send("#{name}_id_will_change!")
|
37
|
+
super(value)
|
38
|
+
end
|
39
|
+
|
22
40
|
before_save do
|
23
41
|
send(attacher).store!
|
24
42
|
end
|
@@ -27,6 +45,77 @@ module Refile
|
|
27
45
|
send(attacher).delete!
|
28
46
|
end
|
29
47
|
end
|
48
|
+
|
49
|
+
# Macro which generates accessors for assigning multiple attachments at
|
50
|
+
# once. This is primarily useful together with multiple file uploads.
|
51
|
+
#
|
52
|
+
# The name of the generated accessors will be the name of the association
|
53
|
+
# and the name of the attachment in the associated model. So if a `Post`
|
54
|
+
# accepts attachments for `images`, and the attachment in the `Image`
|
55
|
+
# model is named `file`, then the accessors will be named `images_files`.
|
56
|
+
#
|
57
|
+
# @example in model
|
58
|
+
# class Post
|
59
|
+
# has_many :images, dependent: :destroy
|
60
|
+
# accepts_attachments_for :images
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# @example in associated model
|
64
|
+
# class Image
|
65
|
+
# attachment :image
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# @example in form
|
69
|
+
# <%= form_for @post do |form| %>
|
70
|
+
# <%= form.attachment_field :images_files, multiple: true %>
|
71
|
+
# <% end %>
|
72
|
+
#
|
73
|
+
# @param [Symbol] association_name Name of the association
|
74
|
+
# @param [Symbol] attachment Name of the attachment in the associated model
|
75
|
+
# @param [Symbol] append If true, new files are appended instead of replacing the entire list of associated models.
|
76
|
+
# @return [void]
|
77
|
+
def accepts_attachments_for(association_name, attachment: :file, append: false)
|
78
|
+
association = reflect_on_association(association_name)
|
79
|
+
name = "#{association_name}_#{attachment.to_s.pluralize}"
|
80
|
+
|
81
|
+
mod = Module.new do
|
82
|
+
define_method :"#{name}_attachment_definition" do
|
83
|
+
association.klass.send("#{attachment}_attachment_definition")
|
84
|
+
end
|
85
|
+
|
86
|
+
define_method :"#{name}_data" do
|
87
|
+
if send(association_name).all? { |record| record.send("#{attachment}_attacher").valid? }
|
88
|
+
send(association_name).map(&:"#{attachment}_data").select(&:present?)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
define_method :"#{name}" do
|
93
|
+
send(association_name).map(&attachment)
|
94
|
+
end
|
95
|
+
|
96
|
+
define_method :"#{name}=" do |files|
|
97
|
+
cache, files = files.partition { |file| file.is_a?(String) }
|
98
|
+
|
99
|
+
cache = Refile.parse_json(cache.first)
|
100
|
+
|
101
|
+
if not append and (files.present? or cache.present?)
|
102
|
+
send("#{association_name}=", [])
|
103
|
+
end
|
104
|
+
|
105
|
+
if files.empty? and cache.present?
|
106
|
+
cache.select(&:present?).each do |file|
|
107
|
+
send(association_name).build(attachment => file.to_json)
|
108
|
+
end
|
109
|
+
else
|
110
|
+
files.select(&:present?).each do |file|
|
111
|
+
send(association_name).build(attachment => file)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
include mod
|
118
|
+
end
|
30
119
|
end
|
31
120
|
end
|
32
121
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Refile
|
2
|
+
# @api private
|
3
|
+
class AttachmentDefinition
|
4
|
+
attr_reader :record, :name, :cache, :store, :options, :type, :valid_extensions, :valid_content_types
|
5
|
+
attr_accessor :remove
|
6
|
+
|
7
|
+
def initialize(name, cache:, store:, raise_errors: true, type: nil, extension: nil, content_type: nil)
|
8
|
+
@name = name
|
9
|
+
@raise_errors = raise_errors
|
10
|
+
@cache_name = cache
|
11
|
+
@store_name = store
|
12
|
+
@type = type
|
13
|
+
@valid_extensions = [extension].flatten if extension
|
14
|
+
@valid_content_types = [content_type].flatten if content_type
|
15
|
+
@valid_content_types ||= Refile.types.fetch(type).content_type if type
|
16
|
+
end
|
17
|
+
|
18
|
+
def cache
|
19
|
+
Refile.backends.fetch(@cache_name.to_s)
|
20
|
+
end
|
21
|
+
|
22
|
+
def store
|
23
|
+
Refile.backends.fetch(@store_name.to_s)
|
24
|
+
end
|
25
|
+
|
26
|
+
def accept
|
27
|
+
if valid_content_types
|
28
|
+
valid_content_types.join(",")
|
29
|
+
elsif valid_extensions
|
30
|
+
valid_extensions.map { |e| ".#{e}" }.join(",")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def raise_errors?
|
35
|
+
@raise_errors
|
36
|
+
end
|
37
|
+
|
38
|
+
def validate(attacher)
|
39
|
+
errors = []
|
40
|
+
extension_included = valid_extensions && valid_extensions.map(&:downcase).include?(attacher.extension.to_s.downcase)
|
41
|
+
errors << :invalid_extension if valid_extensions and not extension_included
|
42
|
+
errors << :invalid_content_type if valid_content_types and not valid_content_types.include?(attacher.content_type)
|
43
|
+
errors << :too_large if cache.max_size and attacher.size and attacher.size >= cache.max_size
|
44
|
+
errors
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/refile/backend/s3.rb
CHANGED
@@ -1,147 +1 @@
|
|
1
|
-
|
2
|
-
require "open-uri"
|
3
|
-
|
4
|
-
module Refile
|
5
|
-
module Backend
|
6
|
-
# A refile backend which stores files in Amazon S3
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# backend = Refile::Backend::S3.new(
|
10
|
-
# access_key_id: "xyz",
|
11
|
-
# secret_access_key: "abcd1234",
|
12
|
-
# bucket: "my-bucket",
|
13
|
-
# prefix: "files"
|
14
|
-
# )
|
15
|
-
# file = backend.upload(StringIO.new("hello"))
|
16
|
-
# backend.read(file.id) # => "hello"
|
17
|
-
class S3
|
18
|
-
extend Refile::BackendMacros
|
19
|
-
|
20
|
-
attr_reader :access_key_id, :max_size
|
21
|
-
|
22
|
-
# Sets up an S3 backend with the given credentials.
|
23
|
-
#
|
24
|
-
# @param [String] access_key_id
|
25
|
-
# @param [String] secret_access_key
|
26
|
-
# @param [String] bucket The name of the bucket where files will be stored
|
27
|
-
# @param [String] prefix A prefix to add to all files. Prefixes on S3 are kind of like folders.
|
28
|
-
# @param [Integer, nil] max_size The maximum size of an uploaded file
|
29
|
-
# @param [#hash] hasher A hasher which is used to generate ids from files
|
30
|
-
# @param [Hash] s3_options Additional options to initialize S3 with
|
31
|
-
# @see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/Core/Configuration.html
|
32
|
-
# @see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/S3.html
|
33
|
-
def initialize(access_key_id:, secret_access_key:, bucket:, max_size: nil, prefix: nil, hasher: Refile::RandomHasher.new, **s3_options)
|
34
|
-
@access_key_id = access_key_id
|
35
|
-
@secret_access_key = secret_access_key
|
36
|
-
@s3_options = { access_key_id: access_key_id, secret_access_key: secret_access_key }.merge s3_options
|
37
|
-
@s3 = AWS::S3.new @s3_options
|
38
|
-
@bucket_name = bucket
|
39
|
-
@bucket = @s3.buckets[@bucket_name]
|
40
|
-
@hasher = hasher
|
41
|
-
@prefix = prefix
|
42
|
-
@max_size = max_size
|
43
|
-
end
|
44
|
-
|
45
|
-
# Upload a file into this backend
|
46
|
-
#
|
47
|
-
# @param [IO] uploadable An uploadable IO-like object.
|
48
|
-
# @return [Refile::File] The uploaded file
|
49
|
-
verify_uploadable def upload(uploadable)
|
50
|
-
id = @hasher.hash(uploadable)
|
51
|
-
|
52
|
-
if uploadable.is_a?(Refile::File) and uploadable.backend.is_a?(S3) and uploadable.backend.access_key_id == access_key_id
|
53
|
-
uploadable.backend.object(uploadable.id).copy_to(object(id))
|
54
|
-
else
|
55
|
-
object(id).write(uploadable, content_length: uploadable.size)
|
56
|
-
end
|
57
|
-
|
58
|
-
Refile::File.new(self, id)
|
59
|
-
end
|
60
|
-
|
61
|
-
# Get a file from this backend.
|
62
|
-
#
|
63
|
-
# Note that this method will always return a {Refile::File} object, even
|
64
|
-
# if a file with the given id does not exist in this backend. Use
|
65
|
-
# {FileSystem#exists?} to check if the file actually exists.
|
66
|
-
#
|
67
|
-
# @param [Sring] id The id of the file
|
68
|
-
# @return [Refile::File] The retrieved file
|
69
|
-
verify_id def get(id)
|
70
|
-
Refile::File.new(self, id)
|
71
|
-
end
|
72
|
-
|
73
|
-
# Delete a file from this backend
|
74
|
-
#
|
75
|
-
# @param [Sring] id The id of the file
|
76
|
-
# @return [void]
|
77
|
-
verify_id def delete(id)
|
78
|
-
object(id).delete
|
79
|
-
end
|
80
|
-
|
81
|
-
# Return an IO object for the uploaded file which can be used to read its
|
82
|
-
# content.
|
83
|
-
#
|
84
|
-
# @param [Sring] id The id of the file
|
85
|
-
# @return [IO] An IO object containing the file contents
|
86
|
-
verify_id def open(id)
|
87
|
-
Kernel.open(object(id).url_for(:read))
|
88
|
-
end
|
89
|
-
|
90
|
-
# Return the entire contents of the uploaded file as a String.
|
91
|
-
#
|
92
|
-
# @param [String] id The id of the file
|
93
|
-
# @return [String] The file's contents
|
94
|
-
verify_id def read(id)
|
95
|
-
object(id).read
|
96
|
-
rescue AWS::S3::Errors::NoSuchKey
|
97
|
-
nil
|
98
|
-
end
|
99
|
-
|
100
|
-
# Return the size in bytes of the uploaded file.
|
101
|
-
#
|
102
|
-
# @param [Sring] id The id of the file
|
103
|
-
# @return [Integer] The file's size
|
104
|
-
verify_id def size(id)
|
105
|
-
object(id).content_length
|
106
|
-
rescue AWS::S3::Errors::NoSuchKey
|
107
|
-
nil
|
108
|
-
end
|
109
|
-
|
110
|
-
# Return whether the file with the given id exists in this backend.
|
111
|
-
#
|
112
|
-
# @param [Sring] id The id of the file
|
113
|
-
# @return [Boolean]
|
114
|
-
verify_id def exists?(id)
|
115
|
-
object(id).exists?
|
116
|
-
end
|
117
|
-
|
118
|
-
# Remove all files in this backend. You must confirm the deletion by
|
119
|
-
# passing the symbol `:confirm` as an argument to this method.
|
120
|
-
#
|
121
|
-
# @example
|
122
|
-
# backend.clear!(:confirm)
|
123
|
-
# @raise [Refile::Confirm] Unless the `:confirm` symbol has been passed.
|
124
|
-
# @param [:confirm] confirm Pass the symbol `:confirm` to confirm deletion.
|
125
|
-
# @return [void]
|
126
|
-
def clear!(confirm = nil)
|
127
|
-
raise Refile::Confirm unless confirm == :confirm
|
128
|
-
@bucket.objects.with_prefix(@prefix).delete_all
|
129
|
-
end
|
130
|
-
|
131
|
-
# Return a presign signature which can be used to upload a file into this
|
132
|
-
# backend directly.
|
133
|
-
#
|
134
|
-
# @return [Refile::Signature]
|
135
|
-
def presign
|
136
|
-
id = RandomHasher.new.hash
|
137
|
-
signature = @bucket.presigned_post(key: [*@prefix, id].join("/"))
|
138
|
-
signature.where(content_length: @max_size) if @max_size
|
139
|
-
Signature.new(as: "file", id: id, url: signature.url.to_s, fields: signature.fields)
|
140
|
-
end
|
141
|
-
|
142
|
-
verify_id def object(id)
|
143
|
-
@bucket.objects[[*@prefix, id].join("/")]
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
1
|
+
raise "[Refile] the S3 backend has been extracted into a separate gem, see https://github.com/refile/refile-s3"
|