mongoid_grid 0.0.4
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.txt +61 -0
- data/lib/mongoid/grid.rb +169 -0
- data/lib/rack/grid.rb +68 -0
- data/test/test_mongoid_grid.rb +0 -0
- data/test/test_rack_grid.rb +0 -0
- metadata +102 -0
data/README.txt
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
Mongoid::Grid / Rack::Grid
|
2
|
+
|
3
|
+
Mongoid::Grid is a plugin for mongoid that uses GridFS. Heavily inspired
|
4
|
+
by grip (http://github.com/jnunemaker/grip)
|
5
|
+
|
6
|
+
Rack::Grid is used to serve a GridFS file from rack. Mostly copied
|
7
|
+
from http://github.com/skinandbones/rack-gridfs
|
8
|
+
|
9
|
+
Download the source at
|
10
|
+
http://github.com/dusty/mongoid_grid
|
11
|
+
|
12
|
+
|
13
|
+
Installation
|
14
|
+
|
15
|
+
Put the libraries in your project however you want.
|
16
|
+
|
17
|
+
# gem install mongoid_grid
|
18
|
+
|
19
|
+
Or, make your own gem.
|
20
|
+
|
21
|
+
# git clone http://github.com/dusty/mongoid_grid
|
22
|
+
# cd mongoid_grid
|
23
|
+
# gem build mongoid_grid.gemspec
|
24
|
+
|
25
|
+
Then require the libraries you want to use.
|
26
|
+
|
27
|
+
require 'mongoid/grid'
|
28
|
+
require 'rack/grid'
|
29
|
+
|
30
|
+
|
31
|
+
Usage
|
32
|
+
|
33
|
+
class Monkey
|
34
|
+
include Mongoid::Document
|
35
|
+
include Mongoid::Grid
|
36
|
+
field :name
|
37
|
+
attachment :image
|
38
|
+
end
|
39
|
+
|
40
|
+
m = Monkey.create(:name => 'name')
|
41
|
+
|
42
|
+
# To add an attachment
|
43
|
+
m.image = File.open('/tmp/me.jpg')
|
44
|
+
m.save
|
45
|
+
|
46
|
+
# To remove an attachment
|
47
|
+
m.image = nil
|
48
|
+
m.save
|
49
|
+
|
50
|
+
# To get the attachment
|
51
|
+
m.image.read
|
52
|
+
|
53
|
+
# To use Rack::Grid with Sinatra
|
54
|
+
|
55
|
+
configure do
|
56
|
+
use Rack::Grid, :database => 'my_db'
|
57
|
+
end
|
58
|
+
|
59
|
+
<img src="<%= m.image_url %>" alt="<%= m.image_name %>" />
|
60
|
+
|
61
|
+
|
data/lib/mongoid/grid.rb
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'mime/types'
|
2
|
+
require 'mongoid'
|
3
|
+
module Mongoid
|
4
|
+
module Grid
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.send(:extend, ClassMethods)
|
8
|
+
base.send(:include, InstanceMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
##
|
14
|
+
# Declare an attachment for the object
|
15
|
+
#
|
16
|
+
# eg: attachment :image
|
17
|
+
def attachment(name,prefix='grid')
|
18
|
+
##
|
19
|
+
# Callbacks to handle the attachment saving and deleting
|
20
|
+
after_save :create_attachments
|
21
|
+
after_save :delete_attachments
|
22
|
+
after_destroy :destroy_attachments
|
23
|
+
|
24
|
+
##
|
25
|
+
# Fields for the attachment.
|
26
|
+
#
|
27
|
+
# Only the _id is really needed, the others are helpful cached
|
28
|
+
# so you don't need to hit GridFS
|
29
|
+
field "#{name}_id".to_sym, :type => BSON::ObjectID
|
30
|
+
field "#{name}_name".to_sym, :type => String
|
31
|
+
field "#{name}_size".to_sym, :type => Integer
|
32
|
+
field "#{name}_type".to_sym, :type => String
|
33
|
+
|
34
|
+
##
|
35
|
+
# Add this name to the attachment_types
|
36
|
+
attachment_types.push(name).uniq!
|
37
|
+
|
38
|
+
##
|
39
|
+
# Return the GridFS object.
|
40
|
+
# eg: image.filename, image.read
|
41
|
+
define_method(name) do
|
42
|
+
grid.get(attributes["#{name}_id"]) if attributes["#{name}_id"]
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Create a method to set the attachment
|
47
|
+
# eg: object.image = File.open('/tmp/somefile.jpg')
|
48
|
+
define_method("#{name}=") do |file|
|
49
|
+
if file.respond_to?(:read)
|
50
|
+
send(:create_attachment, name, file)
|
51
|
+
else
|
52
|
+
send(:delete_attachment, name, send("#{name}_id"))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Return the relative URL to the file for use with Rack::Grid
|
58
|
+
# eg: /grid/4ba69fde8c8f369a6e000003/somefile.png
|
59
|
+
define_method("#{name}_url") do
|
60
|
+
_id = send("#{name}_id")
|
61
|
+
_name = send("#{name}_name")
|
62
|
+
["/#{prefix}", _id, _name].join('/') if _id && _name
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Accessor to GridFS
|
69
|
+
def grid
|
70
|
+
@grid ||= Mongo::Grid.new(Mongoid.database)
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# All the attachments types for this class
|
75
|
+
def attachment_types
|
76
|
+
@attachment_types ||= []
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
module InstanceMethods
|
82
|
+
|
83
|
+
private
|
84
|
+
##
|
85
|
+
# Accessor to GridFS
|
86
|
+
def grid
|
87
|
+
@grid ||= self.class.grid
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# Holds queue of attachments to create
|
92
|
+
def create_attachment_queue
|
93
|
+
@create_attachment_queue ||= {}
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Holds queue of attachments to delete
|
98
|
+
def delete_attachment_queue
|
99
|
+
@delete_attachment_queue ||= {}
|
100
|
+
end
|
101
|
+
|
102
|
+
##
|
103
|
+
# Attachments we need to add after save.
|
104
|
+
def create_attachment(name,file)
|
105
|
+
if file.respond_to?(:read)
|
106
|
+
filename = file.respond_to?(:original_filename) ?
|
107
|
+
file.original_filename : File.basename(file.path)
|
108
|
+
type = MIME::Types.type_for(filename).first
|
109
|
+
mime = type ? type.content_type : "application/octet-stream"
|
110
|
+
send("#{name}_id=", BSON::ObjectID.new)
|
111
|
+
send("#{name}_name=", filename)
|
112
|
+
send("#{name}_size=", File.size(file))
|
113
|
+
send("#{name}_type=", mime)
|
114
|
+
create_attachment_queue[name] = file
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
##
|
119
|
+
# Save an attachment to GridFS
|
120
|
+
def create_grid_attachment(name,file)
|
121
|
+
grid.put(
|
122
|
+
file.read,
|
123
|
+
:filename => attributes["#{name}_name"],
|
124
|
+
:content_type => attributes["#{name}_type"],
|
125
|
+
:_id => attributes["#{name}_id"]
|
126
|
+
)
|
127
|
+
create_attachment_queue.delete(name)
|
128
|
+
end
|
129
|
+
|
130
|
+
##
|
131
|
+
# Attachments we need to remove after save
|
132
|
+
def delete_attachment(name,id)
|
133
|
+
delete_attachment_queue[name] = id if id.is_a?(BSON::ObjectID)
|
134
|
+
send("#{name}_id=", nil)
|
135
|
+
send("#{name}_name=", nil)
|
136
|
+
send("#{name}_size=", nil)
|
137
|
+
send("#{name}_type=", nil)
|
138
|
+
end
|
139
|
+
|
140
|
+
##
|
141
|
+
# Delete an attachment from GridFS
|
142
|
+
def delete_grid_attachment(name,id)
|
143
|
+
grid.delete(id) if id.is_a?(BSON::ObjectID)
|
144
|
+
delete_attachment_queue.delete(name)
|
145
|
+
end
|
146
|
+
|
147
|
+
##
|
148
|
+
# Create attachments marked for creation
|
149
|
+
def create_attachments
|
150
|
+
create_attachment_queue.each {|k,v| create_grid_attachment(k,v)}
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Delete attachments marked for deletion
|
155
|
+
def delete_attachments
|
156
|
+
delete_attachment_queue.each {|k,v| delete_grid_attachment(k,v)}
|
157
|
+
end
|
158
|
+
|
159
|
+
##
|
160
|
+
# Deletes all attachments from document
|
161
|
+
def destroy_attachments
|
162
|
+
self.class.attachment_types.each do |name|
|
163
|
+
delete_attachment(name, send("#{name}_id"))
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
data/lib/rack/grid.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'mongo'
|
3
|
+
|
4
|
+
module Rack
|
5
|
+
class Grid
|
6
|
+
class ConnectionError < StandardError ; end
|
7
|
+
|
8
|
+
attr_reader :host, :port, :database, :prefix, :db, :username, :password
|
9
|
+
|
10
|
+
def initialize(app, options = {})
|
11
|
+
options = options.each do |k,v|
|
12
|
+
if k.is_a?(Symbol)
|
13
|
+
options[k.to_s] = v
|
14
|
+
options.delete(k)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
options = {
|
18
|
+
'host' => 'localhost',
|
19
|
+
'prefix' => 'grid',
|
20
|
+
'port' => Mongo::Connection::DEFAULT_PORT
|
21
|
+
}.merge(options)
|
22
|
+
|
23
|
+
@app = app
|
24
|
+
@host = options['host']
|
25
|
+
@port = options['port']
|
26
|
+
@database = options['database']
|
27
|
+
@prefix = options['prefix']
|
28
|
+
@username = options['username']
|
29
|
+
@password = options['password']
|
30
|
+
@db = nil
|
31
|
+
|
32
|
+
connect!
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Strip the _id out of the path. This allows the user to send something
|
37
|
+
# like /grid/4ba69fde8c8f369a6e000003/filename.jpg to find the file
|
38
|
+
# with an id of 4ba69fde8c8f369a6e000003.
|
39
|
+
def call(env)
|
40
|
+
request = Rack::Request.new(env)
|
41
|
+
if request.path_info =~ /^\/#{prefix}\/(\w+).*$/
|
42
|
+
grid_request($1)
|
43
|
+
else
|
44
|
+
@app.call(env)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Get file from GridFS or return a 404
|
50
|
+
def grid_request(id)
|
51
|
+
file = Mongo::Grid.new(db).get(BSON::ObjectID.from_string(id))
|
52
|
+
[200, {'Content-Type' => file.content_type}, [file.read]]
|
53
|
+
rescue Mongo::GridError, BSON::InvalidObjectID
|
54
|
+
[404, {'Content-Type' => 'text/plain'}, ['File not found.']]
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def connect!
|
59
|
+
Timeout::timeout(5) do
|
60
|
+
@db = Mongo::Connection.new(host,port).db(database)
|
61
|
+
db.authenticate(username, password) if (username || password)
|
62
|
+
end
|
63
|
+
rescue StandardError => e
|
64
|
+
raise ConnectionError, "Timeout connecting to GridFS (#{e.to_s})"
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
File without changes
|
File without changes
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mongoid_grid
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Dusty Doris
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-08-11 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: mime-types
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: mongoid
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 4067859275
|
44
|
+
segments:
|
45
|
+
- 2
|
46
|
+
- 0
|
47
|
+
- 0
|
48
|
+
- beta
|
49
|
+
- 16
|
50
|
+
version: 2.0.0.beta.16
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
description: Plugin for Mongoid to use GridFS and a Rack helper
|
54
|
+
email: github@dusty.name
|
55
|
+
executables: []
|
56
|
+
|
57
|
+
extensions: []
|
58
|
+
|
59
|
+
extra_rdoc_files:
|
60
|
+
- README.txt
|
61
|
+
files:
|
62
|
+
- README.txt
|
63
|
+
- lib/mongoid/grid.rb
|
64
|
+
- lib/rack/grid.rb
|
65
|
+
- test/test_mongoid_grid.rb
|
66
|
+
- test/test_rack_grid.rb
|
67
|
+
has_rdoc: true
|
68
|
+
homepage: http://github.com/dusty/mongoid_grid
|
69
|
+
licenses: []
|
70
|
+
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
94
|
+
requirements: []
|
95
|
+
|
96
|
+
rubyforge_project: none
|
97
|
+
rubygems_version: 1.3.7
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: Plugin for Mongoid to use GridFS and a Rack helper
|
101
|
+
test_files: []
|
102
|
+
|