neofiles 1.1.4 → 1.2.1
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/app/models/concerns/neofiles/data_store/mongo/file_helper.rb +22 -0
- data/app/models/neofiles/data_store.rb +2 -0
- data/app/models/neofiles/data_store/amazon_s3.rb +95 -0
- data/app/models/neofiles/data_store/mongo.rb +132 -0
- data/app/models/neofiles/data_store/not_found_exception.rb +2 -0
- data/app/models/neofiles/file.rb +32 -134
- data/lib/neofiles.rb +2 -13
- data/lib/neofiles/version.rb +1 -1
- metadata +35 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3a3e40bfe2629b65d69615621cbcdc37ab95e20
|
4
|
+
data.tar.gz: 7f259aec163ff50fc5669735f4477e3c058cd942
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f6faca2b60cb0d6cb706ba969d729b2b25146a8eaeaad7dc937e72aa74a5fa2119ff424f27660b477d1eacca2a716b5e2c59bd9d0b36fc0c6c30fed7433cb47
|
7
|
+
data.tar.gz: 63bb20c3acf34a8e337bb9097454577c46d045de915f5948c810cbb9f38b45c225d08b027d945dbba73ec3dbde29ccff1216cf4769c604ac6e586e614570176d
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Neofiles::DataStore::Mongo::FileHelper
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
has_many :chunks, dependent: :destroy, order: [:n, :asc], class_name: 'Neofiles::FileChunk'
|
6
|
+
field :chunk_size, type: Integer, default: Neofiles::DataStore::Mongo::DEFAULT_CHUNK_SIZE
|
7
|
+
validates :chunk_size, presence: true
|
8
|
+
|
9
|
+
def self.copy_from_mongo_to_amazon_s3(ids)
|
10
|
+
ids.each do |id|
|
11
|
+
begin
|
12
|
+
mongo_object = Neofiles::DataStore::Mongo.find id
|
13
|
+
amazon_object = Neofiles::DataStore::AmazonS3.find(id) rescue nil
|
14
|
+
Neofiles::DataStore::AmazonS3.new(id).write(mongo_object.data) unless amazon_object
|
15
|
+
rescue Neofiles::DataStore::NotFoundException
|
16
|
+
next
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Module for storing and reading files from Amazon S3
|
2
|
+
# If you want to work with amazon s3 you need set values for the following parameters in your config file
|
3
|
+
# amazon_s3_region - the AWS region to connect to. The region is used to construct the client endpoint.
|
4
|
+
# amazon_s3_api, amazon_s3_secret - used to set credentials statically
|
5
|
+
# bucket_name - storage name in amazon_s3. Bucket must have a name that conforms to the naming requirements for non-US Standard regions.
|
6
|
+
# http://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-s3-bucket-naming-requirements.html
|
7
|
+
# File will be named as id of the Neofiles::File object
|
8
|
+
|
9
|
+
require 'aws-sdk'
|
10
|
+
|
11
|
+
class Neofiles::DataStore::AmazonS3
|
12
|
+
|
13
|
+
def self.bucket_name
|
14
|
+
Rails.application.config.neofiles.amazon_s3_bucket
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.find(id)
|
18
|
+
s3_object = new(id)
|
19
|
+
if s3_object.data
|
20
|
+
s3_object
|
21
|
+
else
|
22
|
+
raise Neofiles::DataStore::NotFoundException
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
attr_reader :id, :data, :length, :md5
|
29
|
+
|
30
|
+
def initialize(id)
|
31
|
+
@id = id
|
32
|
+
end
|
33
|
+
|
34
|
+
def data
|
35
|
+
@data ||= client.get_object(
|
36
|
+
bucket: bucket_name,
|
37
|
+
key: s3_key
|
38
|
+
).body.read
|
39
|
+
rescue Aws::S3::Errors::ServiceError
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def length
|
44
|
+
@length ||= data.length
|
45
|
+
end
|
46
|
+
|
47
|
+
def md5
|
48
|
+
@md5 ||= begin
|
49
|
+
md5 = Digest::MD5.new
|
50
|
+
md5 << data
|
51
|
+
md5.hexdigest
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def write(data)
|
56
|
+
if data.is_a? Tempfile
|
57
|
+
data.flush
|
58
|
+
data.rewind
|
59
|
+
data = data.read
|
60
|
+
end
|
61
|
+
|
62
|
+
client.put_object(
|
63
|
+
body: data,
|
64
|
+
bucket: bucket_name,
|
65
|
+
key: s3_key
|
66
|
+
)
|
67
|
+
@data = data
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def s3_key
|
75
|
+
object_id = @id.to_s
|
76
|
+
object_id[0..1] + '/' + object_id[2..4] + '/' + object_id
|
77
|
+
end
|
78
|
+
|
79
|
+
def bucket_name
|
80
|
+
self.class.bucket_name
|
81
|
+
end
|
82
|
+
|
83
|
+
def client
|
84
|
+
@client ||= Aws::S3::Client.new(
|
85
|
+
region: Rails.application.config.neofiles.amazon_s3_region,
|
86
|
+
credentials: Aws::Credentials.new(
|
87
|
+
Rails.application.config.neofiles.amazon_s3_api,
|
88
|
+
Rails.application.config.neofiles.amazon_s3_secret
|
89
|
+
)
|
90
|
+
)
|
91
|
+
rescue Aws::S3::Errors::ServiceError
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
class Neofiles::DataStore::Mongo
|
2
|
+
|
3
|
+
DEFAULT_CHUNK_SIZE = Rails.application.config.neofiles.mongo_default_chunk_size
|
4
|
+
|
5
|
+
def self.chunks(id)
|
6
|
+
Neofiles::FileChunk.where(file_id: id).order_by(n: :asc)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.find(id)
|
10
|
+
if chunks(id).any?
|
11
|
+
new(id)
|
12
|
+
else
|
13
|
+
raise Neofiles::DataStore::NotFoundException
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
attr_reader :id, :data, :length, :md5
|
20
|
+
|
21
|
+
def initialize(id)
|
22
|
+
@id = id
|
23
|
+
end
|
24
|
+
|
25
|
+
def data
|
26
|
+
@data ||= chunks.pluck(:data).map(&:data).join
|
27
|
+
end
|
28
|
+
|
29
|
+
def length
|
30
|
+
@length ||= data.length
|
31
|
+
end
|
32
|
+
|
33
|
+
def md5
|
34
|
+
@md5 ||= begin
|
35
|
+
md5 = Digest::MD5.new
|
36
|
+
md5 << data
|
37
|
+
md5.hexdigest
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def write(data)
|
42
|
+
data_buf = []
|
43
|
+
md5 = Digest::MD5.new
|
44
|
+
length, n = 0, 0
|
45
|
+
|
46
|
+
reading(data) do |io|
|
47
|
+
chunking(io, DEFAULT_CHUNK_SIZE) do |buf|
|
48
|
+
md5 << buf
|
49
|
+
data_buf << buf
|
50
|
+
length += buf.size
|
51
|
+
chunk = chunks.build file_id: id
|
52
|
+
chunk.data = binary_for buf
|
53
|
+
chunk.n = n
|
54
|
+
n += 1
|
55
|
+
chunk.save!
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
@data = data_buf.join
|
60
|
+
@length = length
|
61
|
+
@md5 = md5.hexdigest
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def chunks
|
69
|
+
self.class.chunks id
|
70
|
+
end
|
71
|
+
|
72
|
+
# Yield block with IO stream made from input arg, which can be file name or other IO readable object.
|
73
|
+
def reading(arg, &block)
|
74
|
+
if arg.respond_to?(:read)
|
75
|
+
rewind(arg) do |io|
|
76
|
+
block.call(io)
|
77
|
+
end
|
78
|
+
else
|
79
|
+
open(arg.to_s) do |io|
|
80
|
+
block.call(io)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Split IO stream by chunks chunk_size bytes each and yield each chunk in block.
|
86
|
+
def chunking(io, chunk_size, &block)
|
87
|
+
if io.method(:read).arity == 0
|
88
|
+
data = io.read
|
89
|
+
i = 0
|
90
|
+
loop do
|
91
|
+
offset = i * chunk_size
|
92
|
+
length = i + chunk_size < data.size ? chunk_size : data.size - offset
|
93
|
+
|
94
|
+
break if offset >= data.size
|
95
|
+
|
96
|
+
buf = data[offset, length]
|
97
|
+
block.call(buf)
|
98
|
+
i += 1
|
99
|
+
end
|
100
|
+
else
|
101
|
+
while buf = io.read(chunk_size)
|
102
|
+
block.call(buf)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Construct Mongoid binary object from string of bytes.
|
108
|
+
def binary_for(*buf)
|
109
|
+
BSON::Binary.new buf.join, :generic
|
110
|
+
end
|
111
|
+
|
112
|
+
# Yield IO-like argument to block rewinding it first, if possible.
|
113
|
+
def rewind(io, &block)
|
114
|
+
begin
|
115
|
+
pos = io.pos
|
116
|
+
io.flush
|
117
|
+
io.rewind
|
118
|
+
rescue
|
119
|
+
nil
|
120
|
+
end
|
121
|
+
|
122
|
+
begin
|
123
|
+
block.call(io)
|
124
|
+
ensure
|
125
|
+
begin
|
126
|
+
io.pos = pos
|
127
|
+
rescue
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/app/models/neofiles/file.rb
CHANGED
@@ -44,74 +44,36 @@ class Neofiles::File
|
|
44
44
|
|
45
45
|
include Mongoid::Document
|
46
46
|
include Mongoid::Timestamps
|
47
|
+
include Neofiles::DataStore::Mongo::FileHelper
|
47
48
|
|
48
49
|
store_in collection: Rails.application.config.neofiles.mongo_files_collection, client: Rails.application.config.neofiles.mongo_client
|
49
50
|
|
50
|
-
has_many :chunks, dependent: :destroy, order: [:n, :asc], class_name: 'Neofiles::FileChunk'
|
51
|
-
|
52
|
-
DEFAULT_CHUNK_SIZE = Rails.application.config.neofiles.mongo_default_chunk_size
|
53
|
-
|
54
51
|
field :filename, type: String
|
55
52
|
field :content_type, type: String
|
56
53
|
field :length, type: Integer, default: 0
|
57
|
-
field :chunk_size, type: Integer, default: DEFAULT_CHUNK_SIZE
|
58
54
|
field :md5, type: String, default: Digest::MD5.hexdigest('')
|
59
55
|
field :description, type: String
|
60
56
|
field :owner_type, type: String
|
61
57
|
field :owner_id, type: String
|
62
58
|
field :is_deleted, type: Mongoid::Boolean
|
63
59
|
|
64
|
-
validates :filename, :length, :chunk_size, :md5, presence: true
|
65
|
-
|
66
60
|
before_save :save_file
|
67
61
|
after_save :nullify_unpersisted_file
|
68
62
|
|
69
|
-
|
70
|
-
|
71
|
-
# Yield block for each chunk.
|
72
|
-
def each(&block)
|
73
|
-
chunks.all.order_by([:n, :asc]).each do |chunk|
|
74
|
-
block.call(chunk.to_s)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
# Get a portion of chunks, either via Range of Fixnum (length).
|
79
|
-
def slice(*args)
|
80
|
-
case args.first
|
81
|
-
when Range
|
82
|
-
range = args.first
|
83
|
-
first_chunk = (range.min / chunk_size).floor
|
84
|
-
last_chunk = (range.max / chunk_size).ceil
|
85
|
-
offset = range.min % chunk_size
|
86
|
-
length = range.max - range.min + 1
|
87
|
-
when Fixnum
|
88
|
-
start = args.first
|
89
|
-
start = self.length + start if start < 0
|
90
|
-
length = args.size == 2 ? args.last : 1
|
91
|
-
first_chunk = (start / chunk_size).floor
|
92
|
-
last_chunk = ((start + length) / chunk_size).ceil
|
93
|
-
offset = start % chunk_size
|
94
|
-
end
|
95
|
-
|
96
|
-
data = ''
|
97
|
-
|
98
|
-
chunks.where(n: first_chunk..last_chunk).order_by(n: :asc).each do |chunk|
|
99
|
-
data << chunk
|
100
|
-
end
|
101
|
-
|
102
|
-
data[offset, length]
|
103
|
-
end
|
104
|
-
|
105
63
|
# Chunks bytes concatenated, that is the whole file content.
|
106
64
|
def data
|
107
|
-
|
108
|
-
|
109
|
-
|
65
|
+
self.class.read_data_stores.each do |store|
|
66
|
+
begin
|
67
|
+
return store.find(id).data
|
68
|
+
rescue Neofiles::DataStore::NotFoundException
|
69
|
+
next
|
70
|
+
end
|
71
|
+
end
|
110
72
|
end
|
111
73
|
|
112
74
|
# Encode bytes in base64.
|
113
75
|
def base64
|
114
|
-
Array(
|
76
|
+
Array(data).pack('m')
|
115
77
|
end
|
116
78
|
|
117
79
|
# Encode bytes id data uri.
|
@@ -120,18 +82,6 @@ class Neofiles::File
|
|
120
82
|
"data:#{content_type};base64,#{data}"
|
121
83
|
end
|
122
84
|
|
123
|
-
# Bytes as chunks array, if block is given — yield it.
|
124
|
-
def bytes(&block)
|
125
|
-
if block
|
126
|
-
each { |data| block.call(data) }
|
127
|
-
length
|
128
|
-
else
|
129
|
-
bytes = []
|
130
|
-
each { |data| bytes.push(*data) }
|
131
|
-
bytes
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
85
|
|
136
86
|
|
137
87
|
attr_reader :file
|
@@ -159,26 +109,17 @@ class Neofiles::File
|
|
159
109
|
# File length and md5 hash are computed automatically.
|
160
110
|
def save_file
|
161
111
|
if @file
|
162
|
-
self.
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
chunk = self.chunks.build
|
172
|
-
chunk.data = self.class.binary_for(buf)
|
173
|
-
chunk.n = n
|
174
|
-
n += 1
|
175
|
-
chunk.save!
|
176
|
-
self.chunks.push(chunk)
|
112
|
+
self.class.write_data_stores.each do |store|
|
113
|
+
begin
|
114
|
+
data_store_object = store.new id
|
115
|
+
data_store_object.write @file
|
116
|
+
self.length = data_store_object.length
|
117
|
+
self.md5 = data_store_object.md5
|
118
|
+
rescue => ex
|
119
|
+
notify_airbrake(ex) if defined? notify_airbrake
|
120
|
+
next
|
177
121
|
end
|
178
122
|
end
|
179
|
-
|
180
|
-
self.length = length
|
181
|
-
self.md5 = md5.hexdigest
|
182
123
|
end
|
183
124
|
end
|
184
125
|
|
@@ -193,46 +134,6 @@ class Neofiles::File
|
|
193
134
|
template.neofiles_link self, nil, target: '_blank'
|
194
135
|
end
|
195
136
|
|
196
|
-
# Yield block with IO stream made from input arg, which can be file name or other IO readable object.
|
197
|
-
def self.reading(arg, &block)
|
198
|
-
if arg.respond_to?(:read)
|
199
|
-
self.rewind(arg) do |io|
|
200
|
-
block.call(io)
|
201
|
-
end
|
202
|
-
else
|
203
|
-
open(arg.to_s) do |io|
|
204
|
-
block.call(io)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
# Split IO stream by chunks chunk_size bytes each and yield each chunk in block.
|
210
|
-
def self.chunking(io, chunk_size, &block)
|
211
|
-
if io.method(:read).arity == 0
|
212
|
-
data = io.read
|
213
|
-
i = 0
|
214
|
-
loop do
|
215
|
-
offset = i * chunk_size
|
216
|
-
length = i + chunk_size < data.size ? chunk_size : data.size - offset
|
217
|
-
|
218
|
-
break if offset >= data.size
|
219
|
-
|
220
|
-
buf = data[offset, length]
|
221
|
-
block.call(buf)
|
222
|
-
i += 1
|
223
|
-
end
|
224
|
-
else
|
225
|
-
while buf = io.read(chunk_size)
|
226
|
-
block.call(buf)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
# Construct Mongoid binary object from string of bytes.
|
232
|
-
def self.binary_for(*buf)
|
233
|
-
BSON::Binary.new(buf.join, :generic)
|
234
|
-
end
|
235
|
-
|
236
137
|
# Try different methods to extract file name or path from argument object.
|
237
138
|
def self.extract_basename(object)
|
238
139
|
filename = nil
|
@@ -300,24 +201,21 @@ class Neofiles::File
|
|
300
201
|
class_by_file_name(extract_basename(file_object))
|
301
202
|
end
|
302
203
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
pos = io.pos
|
307
|
-
io.flush
|
308
|
-
io.rewind
|
309
|
-
rescue
|
310
|
-
nil
|
311
|
-
end
|
204
|
+
def self.read_data_stores
|
205
|
+
get_stores_class_name Rails.application.config.neofiles.read_data_stores
|
206
|
+
end
|
312
207
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
208
|
+
def self.write_data_stores
|
209
|
+
get_stores_class_name Rails.application.config.neofiles.write_data_stores
|
210
|
+
end
|
211
|
+
|
212
|
+
# return array with names for each store
|
213
|
+
def self.get_stores_class_name(stores)
|
214
|
+
if stores.is_a?(Array)
|
215
|
+
stores.map { |store| Neofiles::DataStore.const_get(store.camelize) }
|
216
|
+
else
|
217
|
+
get_stores_class_name [stores]
|
321
218
|
end
|
322
219
|
end
|
220
|
+
|
323
221
|
end
|
data/lib/neofiles.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'neofiles/engine'
|
2
|
+
require 'aspect_ratio'
|
2
3
|
|
3
4
|
module Neofiles
|
4
5
|
# Attach Neofiles specific routes in your routes.rb file:
|
@@ -34,8 +35,6 @@ module Neofiles
|
|
34
35
|
# width, height - max width and height after resize
|
35
36
|
# resize_options - {crop: '1'/'0'}, @see Neofiles::ImagesController#show
|
36
37
|
#
|
37
|
-
# Can call ImageMagick.
|
38
|
-
#
|
39
38
|
def resized_image_dimensions(image_file, width, height, resize_options)
|
40
39
|
# dimensions are equal to requested ones if cropping
|
41
40
|
return width, height if crop_requested? resize_options
|
@@ -58,17 +57,7 @@ module Neofiles
|
|
58
57
|
# image fits into requested dimensions, no resizing will occur
|
59
58
|
return image_file_width, image_file_height if image_file_width <= width && image_file_height <= height
|
60
59
|
|
61
|
-
|
62
|
-
command = MiniMagick::CommandBuilder.new(:convert) # convert input file...
|
63
|
-
command.size([image_file_width, image_file_height].join 'x') # with the given dimensions...
|
64
|
-
command.xc('white') # and filled with whites...
|
65
|
-
command.resize([width, height].join 'x') # to fit in the given rectangle...
|
66
|
-
command.push('info:-') # return info about the resulting file
|
67
|
-
|
68
|
-
# ... and send it to ImageMagick
|
69
|
-
# the result will be: xc:white XC 54x100 54x100+0+0 16-bit DirectClass 0.070u 0:00.119
|
70
|
-
# extract dimensions and return them as array of integers
|
71
|
-
MiniMagick::Image.new(nil, nil).run(command).match(/ (\d+)x(\d+) /).values_at(1, 2).map(&:to_i)
|
60
|
+
AspectRatio.resize(image_file_width, image_file_height, width, height).map(&:to_i)
|
72
61
|
|
73
62
|
rescue
|
74
63
|
nil
|
data/lib/neofiles/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neofiles
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konanykhin Ilya
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-10-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -80,6 +80,34 @@ dependencies:
|
|
80
80
|
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 0.2.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: aws-sdk
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: aspect_ratio
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
83
111
|
description: 'Library for managing files: creating & storing, linking to file owners,
|
84
112
|
serving files from MongoDB'
|
85
113
|
email:
|
@@ -106,6 +134,11 @@ files:
|
|
106
134
|
- app/controllers/neofiles/files_controller.rb
|
107
135
|
- app/controllers/neofiles/images_controller.rb
|
108
136
|
- app/helpers/neofiles/neofiles_helper.rb
|
137
|
+
- app/models/concerns/neofiles/data_store/mongo/file_helper.rb
|
138
|
+
- app/models/neofiles/data_store.rb
|
139
|
+
- app/models/neofiles/data_store/amazon_s3.rb
|
140
|
+
- app/models/neofiles/data_store/mongo.rb
|
141
|
+
- app/models/neofiles/data_store/not_found_exception.rb
|
109
142
|
- app/models/neofiles/file.rb
|
110
143
|
- app/models/neofiles/file_chunk.rb
|
111
144
|
- app/models/neofiles/image.rb
|