mongoid-grid_fs 1.0.0 → 1.1.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.
- data/README.md +28 -24
- data/lib/mongoid-grid_fs.rb +358 -311
- data/mongoid-grid_fs.gemspec +5 -1
- data/test/mongoid-grid_fs_test.rb +3 -1
- metadata +35 -3
data/README.md
CHANGED
@@ -1,52 +1,56 @@
|
|
1
1
|
NAME
|
2
2
|
----
|
3
|
-
|
3
|
+
mongoid-grid_fs
|
4
|
+
|
5
|
+
INSTALL
|
6
|
+
-------
|
7
|
+
gem install mongoid-grid_fs
|
4
8
|
|
5
9
|
SYNOPSIS
|
6
10
|
--------
|
7
11
|
|
8
|
-
|
12
|
+
````ruby
|
9
13
|
|
10
|
-
|
14
|
+
require 'mongoid-grid_fs'
|
11
15
|
|
12
|
-
|
16
|
+
g = GridFs.put readable
|
13
17
|
|
14
|
-
|
18
|
+
GridFS.get id
|
15
19
|
|
16
|
-
|
20
|
+
GridFS.delete id
|
17
21
|
|
18
22
|
|
19
|
-
|
23
|
+
````
|
20
24
|
|
21
25
|
DESCRIPTION
|
22
26
|
-----------
|
23
|
-
|
24
|
-
|
27
|
+
mongoid_grid_fs is a pure mongoid 3 / moped implementation of the mongodb
|
28
|
+
grid_fs specification
|
25
29
|
|
26
|
-
|
30
|
+
ref: http://www.mongodb.org/display/DOCS/GridFS+Specification
|
27
31
|
|
28
|
-
|
32
|
+
it has the following features:
|
29
33
|
|
30
|
-
|
31
|
-
|
34
|
+
- implementation is on top of mongoid for portability. moped (the driver) is
|
35
|
+
barely used
|
32
36
|
|
33
|
-
|
37
|
+
- simple, REST-like api
|
34
38
|
|
35
|
-
|
39
|
+
- support for custom namespaces (fs.files vs. image.files)
|
36
40
|
|
37
|
-
|
41
|
+
- pathnames and io-like objects can be written to the grid
|
38
42
|
|
39
|
-
|
43
|
+
- auto-unique pathnames are generated (by default) to avoid collisions using #put
|
40
44
|
|
41
|
-
|
45
|
+
'path/info/a.rb' -> '$object_id/a.rb'
|
42
46
|
|
43
|
-
|
44
|
-
|
47
|
+
- [] and []= methods which allow the grid to be used like a giant file
|
48
|
+
hash in the sky
|
45
49
|
|
46
|
-
|
50
|
+
- supprt for data_uris
|
47
51
|
|
48
|
-
|
52
|
+
````erb
|
49
53
|
|
50
|
-
|
54
|
+
<%= image_tag :src => file.data_uri %>
|
51
55
|
|
52
|
-
|
56
|
+
````
|
data/lib/mongoid-grid_fs.rb
CHANGED
@@ -1,419 +1,466 @@
|
|
1
|
-
require "mongoid"
|
2
|
-
require "mime/types"
|
3
|
-
require "digest/md5"
|
4
|
-
require "cgi"
|
5
|
-
|
6
|
-
class GridFS
|
7
1
|
##
|
8
2
|
#
|
9
|
-
class
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
class GridFS
|
4
|
+
const_set :Version, '1.1.0'
|
5
|
+
|
6
|
+
class << GridFS
|
7
|
+
def version
|
8
|
+
const_get :Version
|
9
|
+
end
|
10
|
+
|
11
|
+
def dependencies
|
12
|
+
{
|
13
|
+
'mongoid' => [ 'mongoid' , ' >= 3.0.1' ] ,
|
14
|
+
'mime/types' => [ 'mime-types' , ' >= 1.19' ] ,
|
15
|
+
}
|
16
|
+
end
|
13
17
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
const_set(:File, Fs.file_model)
|
26
|
-
const_set(:Chunk, Fs.chunk_model)
|
27
|
-
|
28
|
-
to_delegate = %w(
|
29
|
-
put
|
30
|
-
get
|
31
|
-
delete
|
32
|
-
find
|
33
|
-
[]
|
34
|
-
[]=
|
35
|
-
)
|
36
|
-
|
37
|
-
to_delegate.each do |method|
|
38
|
-
class_eval <<-__
|
39
|
-
def GridFS.#{ method }(*args, &block)
|
40
|
-
::GridFS::Fs::#{ method }(*args, &block)
|
18
|
+
def libdir(*args, &block)
|
19
|
+
@libdir ||= File.expand_path(__FILE__).sub(/\.rb$/,'')
|
20
|
+
args.empty? ? @libdir : File.join(@libdir, *args)
|
21
|
+
ensure
|
22
|
+
if block
|
23
|
+
begin
|
24
|
+
$LOAD_PATH.unshift(@libdir)
|
25
|
+
block.call()
|
26
|
+
ensure
|
27
|
+
$LOAD_PATH.shift()
|
41
28
|
end
|
42
|
-
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def load(*libs)
|
33
|
+
libs = libs.join(' ').scan(/[^\s+]+/)
|
34
|
+
libdir{ libs.each{|lib| Kernel.load(lib) } }
|
43
35
|
end
|
44
36
|
end
|
45
|
-
end
|
46
37
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
38
|
+
begin
|
39
|
+
require 'rubygems'
|
40
|
+
rescue LoadError
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
if defined?(gem)
|
45
|
+
dependencies.each do |lib, dependency|
|
46
|
+
gem(*dependency)
|
47
|
+
require(lib)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
require "digest/md5"
|
52
|
+
require "cgi"
|
54
53
|
end
|
55
54
|
|
56
55
|
##
|
57
56
|
#
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
57
|
+
class GridFS
|
58
|
+
class << GridFS
|
59
|
+
attr_accessor :namespace
|
60
|
+
attr_accessor :file_model
|
61
|
+
attr_accessor :chunk_model
|
62
|
+
|
63
|
+
def init!
|
64
|
+
GridFS.build_namespace_for(:Fs)
|
65
|
+
|
66
|
+
GridFS.namespace = Fs
|
67
|
+
GridFS.file_model = Fs.file_model
|
68
|
+
GridFS.chunk_model = Fs.chunk_model
|
69
|
+
|
70
|
+
const_set(:File, Fs.file_model)
|
71
|
+
const_set(:Chunk, Fs.chunk_model)
|
72
|
+
|
73
|
+
to_delegate = %w(
|
74
|
+
put
|
75
|
+
get
|
76
|
+
delete
|
77
|
+
find
|
78
|
+
[]
|
79
|
+
[]=
|
80
|
+
)
|
81
|
+
|
82
|
+
to_delegate.each do |method|
|
83
|
+
class_eval <<-__
|
84
|
+
def GridFS.#{ method }(*args, &block)
|
85
|
+
::GridFS::Fs::#{ method }(*args, &block)
|
86
|
+
end
|
87
|
+
__
|
88
|
+
end
|
66
89
|
end
|
90
|
+
end
|
67
91
|
|
68
|
-
|
92
|
+
##
|
93
|
+
#
|
94
|
+
def GridFS.namespace_for(prefix)
|
95
|
+
prefix = prefix.to_s.downcase
|
96
|
+
const = "::GridFS::#{ prefix.to_s.camelize }"
|
97
|
+
namespace = const.split(/::/).last
|
98
|
+
const_defined?(namespace) ? const_get(namespace) : build_namespace_for(namespace)
|
99
|
+
end
|
69
100
|
|
70
|
-
|
71
|
-
|
101
|
+
##
|
102
|
+
#
|
103
|
+
def GridFS.build_namespace_for(prefix)
|
104
|
+
prefix = prefix.to_s.downcase
|
105
|
+
const = prefix.camelize
|
72
106
|
|
73
|
-
|
74
|
-
|
107
|
+
namespace =
|
108
|
+
Module.new do
|
109
|
+
module_eval(&NamespaceMixin)
|
110
|
+
self
|
111
|
+
end
|
75
112
|
|
76
|
-
|
77
|
-
chunk_model.file_model = file_model
|
113
|
+
const_set(const, namespace)
|
78
114
|
|
79
|
-
|
80
|
-
|
81
|
-
namespace.chunk_model = chunk_model
|
115
|
+
file_model = build_file_model_for(namespace)
|
116
|
+
chunk_model = build_chunk_model_for(namespace)
|
82
117
|
|
83
|
-
|
84
|
-
|
118
|
+
file_model.namespace = namespace
|
119
|
+
chunk_model.namespace = namespace
|
85
120
|
|
86
|
-
|
87
|
-
|
121
|
+
file_model.chunk_model = chunk_model
|
122
|
+
chunk_model.file_model = file_model
|
88
123
|
|
89
|
-
|
90
|
-
|
124
|
+
namespace.prefix = prefix
|
125
|
+
namespace.file_model = file_model
|
126
|
+
namespace.chunk_model = chunk_model
|
91
127
|
|
92
|
-
|
93
|
-
|
94
|
-
attr_accessor :prefix
|
95
|
-
attr_accessor :file_model
|
96
|
-
attr_accessor :chunk_model
|
128
|
+
namespace.send(:const_set, :File, file_model)
|
129
|
+
namespace.send(:const_set, :Chunk, chunk_model)
|
97
130
|
|
98
|
-
|
99
|
-
|
100
|
-
end
|
131
|
+
#at_exit{ file_model.create_indexes rescue nil }
|
132
|
+
#at_exit{ chunk_model.create_indexes rescue nil }
|
101
133
|
|
102
|
-
|
103
|
-
|
104
|
-
end
|
134
|
+
const_get(const)
|
135
|
+
end
|
105
136
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
137
|
+
NamespaceMixin = proc do
|
138
|
+
class << self
|
139
|
+
attr_accessor :prefix
|
140
|
+
attr_accessor :file_model
|
141
|
+
attr_accessor :chunk_model
|
110
142
|
|
111
|
-
|
112
|
-
|
143
|
+
def to_s
|
144
|
+
prefix
|
113
145
|
end
|
114
146
|
|
115
|
-
|
116
|
-
|
147
|
+
def namespace
|
148
|
+
prefix
|
117
149
|
end
|
118
150
|
|
119
|
-
|
120
|
-
|
121
|
-
|
151
|
+
def put(readable, attributes = {})
|
152
|
+
chunks = []
|
153
|
+
file = file_model.new
|
154
|
+
attributes.to_options!
|
122
155
|
|
123
|
-
|
124
|
-
|
125
|
-
|
156
|
+
if attributes.has_key?(:id)
|
157
|
+
file.id = attributes.delete(:id)
|
158
|
+
end
|
126
159
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
n = 0
|
160
|
+
if attributes.has_key?(:_id)
|
161
|
+
file.id = attributes.delete(:_id)
|
162
|
+
end
|
131
163
|
|
132
|
-
|
164
|
+
if attributes.has_key?(:content_type)
|
165
|
+
attributes[:contentType] = attributes.delete(:content_type)
|
166
|
+
end
|
133
167
|
|
134
|
-
|
135
|
-
attributes[:
|
136
|
-
|
168
|
+
if attributes.has_key?(:upload_date)
|
169
|
+
attributes[:uploadDate] = attributes.delete(:upload_date)
|
170
|
+
end
|
137
171
|
|
138
|
-
|
139
|
-
|
140
|
-
|
172
|
+
md5 = Digest::MD5.new
|
173
|
+
length = 0
|
174
|
+
chunkSize = file.chunkSize
|
175
|
+
n = 0
|
141
176
|
|
142
|
-
|
143
|
-
md5 << buf
|
144
|
-
length += buf.size
|
145
|
-
chunk = file.chunks.build
|
146
|
-
chunk.data = binary_for(buf)
|
147
|
-
chunk.n = n
|
148
|
-
n += 1
|
149
|
-
chunk.save!
|
150
|
-
chunks.push(chunk)
|
151
|
-
end
|
177
|
+
GridFS.reading(readable) do |io|
|
152
178
|
|
153
|
-
|
179
|
+
filename =
|
180
|
+
attributes[:filename] ||=
|
181
|
+
[file.id.to_s, GridFS.extract_basename(io)].join('/').squeeze('/')
|
154
182
|
|
155
|
-
|
156
|
-
|
157
|
-
|
183
|
+
content_type =
|
184
|
+
attributes[:contentType] ||=
|
185
|
+
GridFS.extract_content_type(filename) || file.contentType
|
158
186
|
|
159
|
-
|
187
|
+
while((buf = io.read(chunkSize)))
|
188
|
+
md5 << buf
|
189
|
+
length += buf.size
|
190
|
+
chunk = file.chunks.build
|
191
|
+
chunk.data = binary_for(buf)
|
192
|
+
chunk.n = n
|
193
|
+
n += 1
|
194
|
+
chunk.save!
|
195
|
+
chunks.push(chunk)
|
196
|
+
end
|
160
197
|
|
161
|
-
|
162
|
-
file
|
163
|
-
ensure
|
164
|
-
chunks.each{|chunk| chunk.destroy rescue nil} if $!
|
165
|
-
end
|
198
|
+
end
|
166
199
|
|
167
|
-
|
168
|
-
|
169
|
-
|
200
|
+
attributes[:length] ||= length
|
201
|
+
attributes[:uploadDate] ||= Time.now.utc
|
202
|
+
attributes[:md5] ||= md5.hexdigest
|
203
|
+
|
204
|
+
file.update_attributes(attributes)
|
205
|
+
|
206
|
+
file.save!
|
207
|
+
file
|
208
|
+
ensure
|
209
|
+
chunks.each{|chunk| chunk.destroy rescue nil} if $!
|
170
210
|
end
|
171
|
-
|
172
|
-
|
173
|
-
|
211
|
+
|
212
|
+
if defined?(Moped)
|
213
|
+
def binary_for(*buf)
|
214
|
+
Moped::BSON::Binary.new(:generic, buf.join)
|
215
|
+
end
|
216
|
+
else
|
217
|
+
def binary_for(buf)
|
218
|
+
BSON::Binary.new(buf.bytes.to_a)
|
219
|
+
end
|
174
220
|
end
|
175
|
-
end
|
176
221
|
|
177
|
-
|
178
|
-
|
179
|
-
|
222
|
+
def get(id)
|
223
|
+
file_model.find(id)
|
224
|
+
end
|
180
225
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
226
|
+
def delete(id)
|
227
|
+
file_model.find(id).destroy
|
228
|
+
rescue
|
229
|
+
nil
|
230
|
+
end
|
186
231
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
232
|
+
def where(conditions = {})
|
233
|
+
case conditions
|
234
|
+
when String
|
235
|
+
file_model.where(:filename => conditions)
|
236
|
+
else
|
237
|
+
file_model.where(conditions)
|
238
|
+
end
|
193
239
|
end
|
194
|
-
end
|
195
240
|
|
196
|
-
|
197
|
-
|
198
|
-
|
241
|
+
def find(*args)
|
242
|
+
where(*args).first
|
243
|
+
end
|
199
244
|
|
200
|
-
|
201
|
-
|
202
|
-
|
245
|
+
def [](filename)
|
246
|
+
file_model.where(:filename => filename.to_s).first
|
247
|
+
end
|
203
248
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
249
|
+
def []=(filename, readable)
|
250
|
+
file = self[filename]
|
251
|
+
file.destroy if file
|
252
|
+
put(readable, :filename => filename.to_s)
|
253
|
+
end
|
209
254
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
255
|
+
# TODO - opening with a mode = 'w' should return a GridIO::IOProxy
|
256
|
+
# implementing a StringIO-like interface
|
257
|
+
#
|
258
|
+
def open(filename, mode = 'r', &block)
|
259
|
+
raise NotImplementedError
|
260
|
+
end
|
215
261
|
end
|
216
262
|
end
|
217
|
-
end
|
218
263
|
|
219
|
-
##
|
220
|
-
#
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
264
|
+
##
|
265
|
+
#
|
266
|
+
def GridFS.build_file_model_for(namespace)
|
267
|
+
prefix = namespace.name.split(/::/).last.downcase
|
268
|
+
file_model_name = "#{ namespace.name }::File"
|
269
|
+
chunk_model_name = "#{ namespace.name }::Chunk"
|
225
270
|
|
226
|
-
|
227
|
-
|
271
|
+
Class.new do
|
272
|
+
include Mongoid::Document
|
228
273
|
|
229
|
-
|
274
|
+
singleton_class = class << self; self; end
|
230
275
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
276
|
+
singleton_class.instance_eval do
|
277
|
+
define_method(:name){ file_model_name }
|
278
|
+
attr_accessor :chunk_model
|
279
|
+
attr_accessor :namespace
|
280
|
+
end
|
236
281
|
|
237
|
-
|
282
|
+
self.default_collection_name = "#{ prefix }.files"
|
238
283
|
|
239
|
-
|
240
|
-
|
284
|
+
field(:filename, :type => String)
|
285
|
+
field(:contentType, :type => String, :default => 'application/octet-stream')
|
241
286
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
287
|
+
field(:length, :type => Integer, :default => 0)
|
288
|
+
field(:chunkSize, :type => Integer, :default => (256 * (2 ** 20)))
|
289
|
+
field(:uploadDate, :type => Date, :default => Time.now.utc)
|
290
|
+
field(:md5, :type => String, :default => Digest::MD5.hexdigest(''))
|
246
291
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
292
|
+
%w( filename contentType length chunkSize uploadDate md5 ).each do |f|
|
293
|
+
validates_presence_of(f)
|
294
|
+
end
|
295
|
+
validates_uniqueness_of(:filename)
|
251
296
|
|
252
|
-
|
297
|
+
has_many(:chunks, :class_name => chunk_model_name, :inverse_of => :files, :dependent => :destroy, :order => [:n, :asc])
|
253
298
|
|
254
|
-
|
299
|
+
index({:filename => 1}, :unique => true)
|
255
300
|
|
256
|
-
|
257
|
-
|
258
|
-
|
301
|
+
def path
|
302
|
+
filename
|
303
|
+
end
|
259
304
|
|
260
|
-
|
261
|
-
|
262
|
-
|
305
|
+
def basename
|
306
|
+
::File.basename(filename)
|
307
|
+
end
|
263
308
|
|
264
|
-
|
265
|
-
|
266
|
-
|
309
|
+
def prefix
|
310
|
+
self.class.namespace.prefix
|
311
|
+
end
|
267
312
|
|
268
|
-
|
269
|
-
|
270
|
-
|
313
|
+
def each(&block)
|
314
|
+
chunks.all.order_by([:n, :asc]).each do |chunk|
|
315
|
+
block.call(chunk.to_s)
|
316
|
+
end
|
271
317
|
end
|
272
|
-
end
|
273
318
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
319
|
+
def data
|
320
|
+
data = ''
|
321
|
+
each{|chunk| data << chunk}
|
322
|
+
data
|
323
|
+
end
|
279
324
|
|
280
|
-
|
281
|
-
|
282
|
-
|
325
|
+
def base64
|
326
|
+
Array(to_s).pack('m')
|
327
|
+
end
|
283
328
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
329
|
+
def data_uri(options = {})
|
330
|
+
data = base64.chomp
|
331
|
+
"data:#{ content_type };base64,".concat(data)
|
332
|
+
end
|
288
333
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
334
|
+
def bytes(&block)
|
335
|
+
if block
|
336
|
+
each{|data| block.call(data)}
|
337
|
+
length
|
338
|
+
else
|
339
|
+
bytes = []
|
340
|
+
each{|data| bytes.push(*data)}
|
341
|
+
bytes
|
342
|
+
end
|
297
343
|
end
|
298
|
-
end
|
299
344
|
|
300
|
-
|
301
|
-
|
302
|
-
|
345
|
+
def close
|
346
|
+
self
|
347
|
+
end
|
303
348
|
|
304
|
-
|
305
|
-
|
306
|
-
|
349
|
+
def content_type
|
350
|
+
contentType
|
351
|
+
end
|
307
352
|
|
308
|
-
|
309
|
-
|
310
|
-
|
353
|
+
def update_date
|
354
|
+
updateDate
|
355
|
+
end
|
311
356
|
|
312
|
-
|
313
|
-
|
314
|
-
|
357
|
+
def created_at
|
358
|
+
updateDate
|
359
|
+
end
|
315
360
|
|
316
|
-
|
317
|
-
|
361
|
+
def namespace
|
362
|
+
self.class.namespace
|
363
|
+
end
|
318
364
|
end
|
319
365
|
end
|
320
|
-
end
|
321
366
|
|
322
|
-
##
|
323
|
-
#
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
367
|
+
##
|
368
|
+
#
|
369
|
+
def GridFS.build_chunk_model_for(namespace)
|
370
|
+
prefix = namespace.name.split(/::/).last.downcase
|
371
|
+
file_model_name = "#{ namespace.name }::File"
|
372
|
+
chunk_model_name = "#{ namespace.name }::Chunk"
|
328
373
|
|
329
|
-
|
330
|
-
|
374
|
+
Class.new do
|
375
|
+
include Mongoid::Document
|
331
376
|
|
332
|
-
|
377
|
+
singleton_class = class << self; self; end
|
333
378
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
379
|
+
singleton_class.instance_eval do
|
380
|
+
define_method(:name){ chunk_model_name }
|
381
|
+
attr_accessor :file_model
|
382
|
+
attr_accessor :namespace
|
383
|
+
end
|
339
384
|
|
340
|
-
|
385
|
+
self.default_collection_name = "#{ prefix }.chunks"
|
341
386
|
|
342
|
-
|
343
|
-
|
387
|
+
field(:n, :type => Integer, :default => 0)
|
388
|
+
field(:data, :type => (defined?(Moped) ? Moped::BSON::Binary : BSON::Binary))
|
344
389
|
|
345
|
-
|
390
|
+
belongs_to(:file, :foreign_key => :files_id, :class_name => file_model_name)
|
346
391
|
|
347
|
-
|
392
|
+
index({:files_id => 1, :n => -1}, :unique => true)
|
348
393
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
def to_s
|
354
|
-
data.data
|
355
|
-
end
|
394
|
+
def namespace
|
395
|
+
self.class.namespace
|
396
|
+
end
|
356
397
|
|
357
|
-
|
358
|
-
|
359
|
-
|
398
|
+
def to_s
|
399
|
+
data.data
|
400
|
+
end
|
360
401
|
|
361
|
-
|
362
|
-
#
|
363
|
-
def GridFS.reading(arg, &block)
|
364
|
-
if arg.respond_to?(:read)
|
365
|
-
rewind(arg) do |io|
|
366
|
-
block.call(io)
|
367
|
-
end
|
368
|
-
else
|
369
|
-
open(arg.to_s) do |io|
|
370
|
-
block.call(io)
|
402
|
+
alias_method 'to_str', 'to_s'
|
371
403
|
end
|
372
404
|
end
|
373
|
-
end
|
374
405
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
406
|
+
##
|
407
|
+
#
|
408
|
+
def GridFS.reading(arg, &block)
|
409
|
+
if arg.respond_to?(:read)
|
410
|
+
rewind(arg) do |io|
|
411
|
+
block.call(io)
|
412
|
+
end
|
413
|
+
else
|
414
|
+
open(arg.to_s) do |io|
|
415
|
+
block.call(io)
|
416
|
+
end
|
417
|
+
end
|
382
418
|
end
|
383
419
|
|
384
|
-
|
385
|
-
block.call(io)
|
386
|
-
ensure
|
420
|
+
def GridFS.rewind(io, &block)
|
387
421
|
begin
|
388
|
-
|
422
|
+
pos = io.pos
|
423
|
+
io.flush
|
424
|
+
io.rewind
|
389
425
|
rescue
|
390
426
|
nil
|
391
427
|
end
|
428
|
+
|
429
|
+
begin
|
430
|
+
block.call(io)
|
431
|
+
ensure
|
432
|
+
begin
|
433
|
+
io.pos = pos
|
434
|
+
rescue
|
435
|
+
nil
|
436
|
+
end
|
437
|
+
end
|
392
438
|
end
|
393
|
-
end
|
394
439
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
440
|
+
def GridFS.extract_basename(object)
|
441
|
+
filename = nil
|
442
|
+
[:original_path, :original_filename, :path, :filename, :pathname].each do |msg|
|
443
|
+
if object.respond_to?(msg)
|
444
|
+
filename = object.send(msg)
|
445
|
+
break
|
446
|
+
end
|
401
447
|
end
|
448
|
+
filename ? cleanname(filename) : nil
|
402
449
|
end
|
403
|
-
filename ? cleanname(filename) : nil
|
404
|
-
end
|
405
450
|
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
451
|
+
def GridFS.extract_content_type(filename)
|
452
|
+
content_type = MIME::Types.type_for(::File.basename(filename.to_s)).first
|
453
|
+
content_type.to_s if content_type
|
454
|
+
end
|
410
455
|
|
411
|
-
|
412
|
-
|
413
|
-
|
456
|
+
def GridFS.cleanname(pathname)
|
457
|
+
basename = ::File.basename(pathname.to_s)
|
458
|
+
CGI.unescape(basename).gsub(%r/[^0-9a-zA-Z_@)(~.-]/, '_').gsub(%r/_+/,'_')
|
459
|
+
end
|
414
460
|
end
|
415
|
-
end
|
416
461
|
|
417
|
-
|
462
|
+
##
|
463
|
+
#
|
464
|
+
GridFs = GridFS
|
418
465
|
|
419
|
-
GridFS.init!
|
466
|
+
GridFS.init!
|
data/mongoid-grid_fs.gemspec
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
Gem::Specification::new do |spec|
|
5
5
|
spec.name = "mongoid-grid_fs"
|
6
|
-
spec.version = "1.
|
6
|
+
spec.version = "1.1.0"
|
7
7
|
spec.platform = Gem::Platform::RUBY
|
8
8
|
spec.summary = "mongoid-grid_fs"
|
9
9
|
spec.description = "a mongoid 3/moped compatible implementation of the grid_fs specification"
|
@@ -26,6 +26,10 @@ Gem::Specification::new do |spec|
|
|
26
26
|
spec.test_files = nil
|
27
27
|
|
28
28
|
|
29
|
+
spec.add_dependency(*["mongoid", " >= 3.0.1"])
|
30
|
+
|
31
|
+
spec.add_dependency(*["mime-types", " >= 1.19"])
|
32
|
+
|
29
33
|
|
30
34
|
spec.extensions.push(*[])
|
31
35
|
|
@@ -142,6 +142,8 @@ Testing GridFs do
|
|
142
142
|
|
143
143
|
protected
|
144
144
|
def object_id_re
|
145
|
-
|
145
|
+
object_id = defined?(Moped) ? Moped::BSON::ObjectId.new : BSON::ObjectId.new
|
146
|
+
|
147
|
+
%r| \w{#{ object_id.to_s.size }} |iomx
|
146
148
|
end
|
147
149
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-grid_fs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,40 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
13
|
-
dependencies:
|
12
|
+
date: 2012-07-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mongoid
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.0.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: mime-types
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.19'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.19'
|
14
46
|
description: a mongoid 3/moped compatible implementation of the grid_fs specification
|
15
47
|
email: ara.t.howard@gmail.com
|
16
48
|
executables: []
|