rack-gridfs 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -2,19 +2,23 @@
2
2
 
3
3
  Rack:GridFS is a Rack middleware for creating HTTP endpoints for files
4
4
  stored in MongoDB's GridFS. You can configure a prefix string which
5
- will be used to match the path of a request and create a key for looking
5
+ will be used to match the path of a request and supply an id for looking
6
6
  up the file in the GridFS store.
7
7
 
8
8
  For example,
9
9
 
10
- GET '/gridfs/images/foo.jpg'
10
+ GET '/gridfs/someobjectid'
11
11
 
12
- If the prefix is "gridfs", then the key will be be "images/foo.jpg".
12
+ If the prefix is "gridfs", then the id will be be "someobjectid".
13
13
 
14
- == Dependencies
14
+ == Mongo Driver Compatibility Notes
15
15
 
16
- * ActiveSupport (activesupport)
17
- * Mongo Ruby Driver v0.15.1+ (mongo)
16
+ This version is currently based off of mongo-0.20.1.
17
+
18
+ As of mongo-0.19.1, there have been significant changes to GridFS. I do
19
+ not plan to support versions of the mongo driver prior to 0.19. There are
20
+ some compatibility issues with mongo-0.19 vs. mongo-0.20 (Mongo::ObjectID
21
+ vs. BSON::ObjectID). For now, I am choosing to support mongo-0.20.
18
22
 
19
23
  == Installation
20
24
 
@@ -31,14 +35,10 @@ You must specify MongoDB database details:
31
35
  - database: the MongoDB database to connect to.
32
36
  - prefix: a string used to match against incoming paths and route to through the middleware. Default 'gridfs'.
33
37
 
34
- == Caveats
35
-
36
- This is an experimental project. The Ruby GridFS adaptor is still pretty new and the performance
37
- is known to be slow. I wouldn't recommend using this middleware for anything high-volume in
38
- production.
39
-
40
38
  == Sinatra Example
41
39
 
40
+ # TODO: THIS COULD USE A LOT MORE EXPLANATION!
41
+
42
42
  require 'rubygems'
43
43
  require 'sinatra'
44
44
 
@@ -46,9 +46,9 @@ production.
46
46
  use Rack::GridFS, :hostname => 'localhost', :port => 27017, :database => 'test', :prefix => 'gridfs'
47
47
 
48
48
  get /.*/ do
49
- "Whatchya talking about?"
49
+ "The URL did not match a file in GridFS."
50
50
  end
51
51
 
52
52
  == Copyright
53
53
 
54
- Copyright (c) 2009 Blake Carlson. See LICENSE for details.
54
+ Copyright (c) 2010 Blake Carlson. See LICENSE for details.
data/Rakefile CHANGED
@@ -12,12 +12,11 @@ begin
12
12
  gem.rubyforge_project = "rack-gridfs"
13
13
 
14
14
  gem.add_dependency('rack')
15
- gem.add_dependency('activesupport')
16
- gem.add_dependency('mongo', '0.15.1')
15
+ gem.add_dependency('mongo', '>=0.20.1')
17
16
 
18
17
  gem.add_development_dependency('mocha', '0.9.4')
19
18
  gem.add_development_dependency('rack-test')
20
- gem.add_development_dependency('thoughtbot-shoulda')
19
+ gem.add_development_dependency('shoulda')
21
20
  end
22
21
  Jeweler::GemcutterTasks.new
23
22
  Jeweler::RubyforgeTasks.new do |rubyforge|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
data/lib/rack/gridfs.rb CHANGED
@@ -1,29 +1,27 @@
1
1
  require 'timeout'
2
2
  require 'mongo'
3
- require 'mongo/gridfs'
4
- require 'active_support/core_ext'
5
3
 
6
4
  module Rack
7
5
 
8
- class GridFSConnectonError < StandardError ; end
6
+ class GridFSConnectionError < StandardError ; end
9
7
 
10
8
  class GridFS
11
9
 
12
- attr_reader :hostname, :port, :database, :prefix, :connection
10
+ attr_reader :hostname, :port, :database, :prefix, :db
13
11
 
14
12
  def initialize(app, options = {})
15
- options.reverse_merge!(
13
+ options = {
16
14
  :hostname => 'localhost',
17
- :port => Mongo::Connection::DEFAULT_PORT,
18
- :prefix => 'gridfs'
19
- )
15
+ :prefix => 'gridfs',
16
+ :port => Mongo::Connection::DEFAULT_PORT
17
+ }.merge(options)
20
18
 
21
19
  @app = app
22
20
  @hostname = options[:hostname]
23
21
  @port = options[:port]
24
22
  @database = options[:database]
25
23
  @prefix = options[:prefix]
26
- @connection = nil
24
+ @db = nil
27
25
 
28
26
  connect!
29
27
  end
@@ -37,28 +35,21 @@ module Rack
37
35
  end
38
36
  end
39
37
 
40
- def not_found
38
+ def gridfs_request(id)
39
+ file = Mongo::Grid.new(db).get(BSON::ObjectID.from_string(id))
40
+ [200, {'Content-Type' => file.content_type}, [file.read]]
41
+ rescue Mongo::GridError, BSON::InvalidObjectID
41
42
  [404, {'Content-Type' => 'text/plain'}, ['File not found.']]
42
43
  end
43
-
44
- def gridfs_request(key)
45
- if ::GridFS::GridStore.exist?(connection, key)
46
- ::GridFS::GridStore.open(connection, key, 'r') do |file|
47
- [200, {'Content-Type' => file.content_type}, [file.read]]
48
- end
49
- else
50
- not_found
51
- end
52
- end
53
44
 
54
45
  private
55
46
 
56
47
  def connect!
57
48
  Timeout::timeout(5) do
58
- @connection = Mongo::Connection.new(hostname).db(database)
49
+ @db = Mongo::Connection.new(hostname).db(database)
59
50
  end
60
51
  rescue Exception => e
61
- raise Rack::GridFSConnectonError, "Unable to connect to the MongoDB server (#{e.to_s})"
52
+ raise Rack::GridFSConnectionError, "Unable to connect to the MongoDB server (#{e.to_s})"
62
53
  end
63
54
 
64
55
  end
data/rack-gridfs.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rack-gridfs}
8
- s.version = "0.2.0"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Blake Carlson"]
12
- s.date = %q{2009-10-19}
12
+ s.date = %q{2010-05-11}
13
13
  s.email = %q{blake@coin-operated.net}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
@@ -47,26 +47,23 @@ Gem::Specification.new do |s|
47
47
 
48
48
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
49
  s.add_runtime_dependency(%q<rack>, [">= 0"])
50
- s.add_runtime_dependency(%q<activesupport>, [">= 0"])
51
- s.add_runtime_dependency(%q<mongo>, ["= 0.15.1"])
50
+ s.add_runtime_dependency(%q<mongo>, [">= 0.20.1"])
52
51
  s.add_development_dependency(%q<mocha>, ["= 0.9.4"])
53
52
  s.add_development_dependency(%q<rack-test>, [">= 0"])
54
- s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
53
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
55
54
  else
56
55
  s.add_dependency(%q<rack>, [">= 0"])
57
- s.add_dependency(%q<activesupport>, [">= 0"])
58
- s.add_dependency(%q<mongo>, ["= 0.15.1"])
56
+ s.add_dependency(%q<mongo>, [">= 0.20.1"])
59
57
  s.add_dependency(%q<mocha>, ["= 0.9.4"])
60
58
  s.add_dependency(%q<rack-test>, [">= 0"])
61
- s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
59
+ s.add_dependency(%q<shoulda>, [">= 0"])
62
60
  end
63
61
  else
64
62
  s.add_dependency(%q<rack>, [">= 0"])
65
- s.add_dependency(%q<activesupport>, [">= 0"])
66
- s.add_dependency(%q<mongo>, ["= 0.15.1"])
63
+ s.add_dependency(%q<mongo>, [">= 0.20.1"])
67
64
  s.add_dependency(%q<mocha>, ["= 0.9.4"])
68
65
  s.add_dependency(%q<rack-test>, [">= 0"])
69
- s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
66
+ s.add_dependency(%q<shoulda>, [">= 0"])
70
67
  end
71
68
  end
72
69
 
data/test/gridfs_test.rb CHANGED
@@ -3,10 +3,6 @@ require 'test_helper'
3
3
  class Rack::GridFSTest < Test::Unit::TestCase
4
4
  include Rack::Test::Methods
5
5
 
6
- def options_for_gridfs
7
- { :hostname => 'myhostname.mydomain', :port => 8765, :database => 'mydatabase', :prefix => 'myprefix' }
8
- end
9
-
10
6
  def stub_mongodb_connection
11
7
  Rack::GridFS.any_instance.stubs(:connect!).returns(true)
12
8
  end
@@ -20,19 +16,16 @@ class Rack::GridFSTest < Test::Unit::TestCase
20
16
  end
21
17
 
22
18
  def app
19
+ gridfs_opts = test_database_options
23
20
  Rack::Builder.new do
24
- use Rack::GridFS, :hostname => 'localhost', :port => 27017, :database => 'test', :prefix => 'gridfs'
21
+ use Rack::GridFS, gridfs_opts
25
22
  run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
26
23
  end
27
24
  end
28
25
 
29
- def load_artifact(filename, key, content_type)
30
- GridFS::GridStore.unlink(db, key)
31
- GridFS::GridStore.open(db, key, 'w', :content_type => content_type) do |dest|
32
- File.open(File.join(File.dirname(__FILE__), 'artifacts', filename), 'r') do |orig|
33
- dest.puts orig.read
34
- end
35
- end
26
+ def load_artifact(filename, content_type)
27
+ contents = File.read(File.join(File.dirname(__FILE__), 'artifacts', filename))
28
+ Mongo::Grid.new(db).put(contents, :filename => filename, :content_type => content_type)
36
29
  end
37
30
 
38
31
  context "Rack::GridFS" do
@@ -41,51 +34,52 @@ class Rack::GridFSTest < Test::Unit::TestCase
41
34
 
42
35
  setup do
43
36
  stub_mongodb_connection
37
+ @options = { :hostname => 'myhostname.mydomain', :port => 8765, :database => 'mydatabase', :prefix => 'myprefix' }
44
38
  end
45
39
 
46
40
  should "have a hostname option" do
47
- mware = Rack::GridFS.new(nil, options_for_gridfs)
48
- assert_equal options_for_gridfs[:hostname], mware.hostname
41
+ mware = Rack::GridFS.new(nil, @options)
42
+ assert_equal @options[:hostname], mware.hostname
49
43
  end
50
44
 
51
45
  should "have a default hostname" do
52
- mware = Rack::GridFS.new(nil, options_for_gridfs.except(:hostname))
46
+ mware = Rack::GridFS.new(nil, @options.except(:hostname))
53
47
  assert_equal 'localhost', mware.hostname
54
48
  end
55
49
 
56
50
  should "have a port option" do
57
- mware = Rack::GridFS.new(nil, options_for_gridfs)
58
- assert_equal options_for_gridfs[:port], mware.port
51
+ mware = Rack::GridFS.new(nil, @options)
52
+ assert_equal @options[:port], mware.port
59
53
  end
60
54
 
61
55
  should "have a default port" do
62
- mware = Rack::GridFS.new(nil, options_for_gridfs.except(:port))
56
+ mware = Rack::GridFS.new(nil, @options.except(:port))
63
57
  assert_equal Mongo::Connection::DEFAULT_PORT, mware.port
64
58
  end
65
59
 
66
60
  should "have a database option" do
67
- mware = Rack::GridFS.new(nil, options_for_gridfs)
68
- assert_equal options_for_gridfs[:database], mware.database
61
+ mware = Rack::GridFS.new(nil, @options)
62
+ assert_equal @options[:database], mware.database
69
63
  end
70
64
 
71
65
  should "not have a default database" do
72
- mware = Rack::GridFS.new(nil, options_for_gridfs.except(:database))
66
+ mware = Rack::GridFS.new(nil, @options.except(:database))
73
67
  assert_nil mware.database
74
68
  end
75
69
 
76
70
  should "have a prefix option" do
77
- mware = Rack::GridFS.new(nil, options_for_gridfs)
78
- assert_equal mware.prefix, options_for_gridfs[:prefix]
71
+ mware = Rack::GridFS.new(nil, @options)
72
+ assert_equal mware.prefix, @options[:prefix]
79
73
  end
80
74
 
81
75
  should "have a default prefix" do
82
- mware = Rack::GridFS.new(nil, options_for_gridfs.except(:prefix))
76
+ mware = Rack::GridFS.new(nil, @options.except(:prefix))
83
77
  assert_equal mware.prefix, 'gridfs'
84
78
  end
85
79
 
86
80
  should "connect to the MongoDB server" do
87
81
  Rack::GridFS.any_instance.expects(:connect!).returns(true).once
88
- Rack::GridFS.new(nil, options_for_gridfs)
82
+ Rack::GridFS.new(nil, @options)
89
83
  end
90
84
 
91
85
  end
@@ -98,29 +92,33 @@ class Rack::GridFSTest < Test::Unit::TestCase
98
92
  end
99
93
  end
100
94
 
101
- context "with a files in GridFS" do
95
+ context "with files in GridFS" do
102
96
  setup do
103
- load_artifact('test.txt', 'test.txt', 'text/plain')
104
- load_artifact('test.html', 'test.html', 'text/html')
97
+ @text_id = load_artifact('test.txt', 'text/plain')
98
+ @html_id = load_artifact('test.html', 'text/html')
99
+ end
100
+
101
+ teardown do
102
+ db.collection('fs.files').remove
105
103
  end
106
104
 
107
105
  should "return TXT files stored in GridFS" do
108
- get '/gridfs/test.txt'
109
- assert_equal "Lorem ipsum dolor sit amet.\n", last_response.body
106
+ get "/gridfs/#{@text_id}"
107
+ assert_equal "Lorem ipsum dolor sit amet.", last_response.body
110
108
  end
111
109
 
112
110
  should "return the proper content type for TXT files" do
113
- get '/gridfs/test.txt'
111
+ get "/gridfs/#{@text_id}"
114
112
  assert_equal 'text/plain', last_response.content_type
115
113
  end
116
114
 
117
115
  should "return HTML files stored in GridFS" do
118
- get '/gridfs/test.html'
116
+ get "/gridfs/#{@html_id}"
119
117
  assert_match /html.*?body.*Test/m, last_response.body
120
118
  end
121
-
119
+
122
120
  should "return the proper content type for HTML files" do
123
- get '/gridfs/test.html'
121
+ get "/gridfs/#{@html_id}"
124
122
  assert_equal 'text/html', last_response.content_type
125
123
  end
126
124
 
@@ -129,15 +127,9 @@ class Rack::GridFSTest < Test::Unit::TestCase
129
127
  assert last_response.not_found?
130
128
  end
131
129
 
132
- should "handle complex file paths" do
133
- load_artifact('test.html', 'stuff/187d/foo.html', 'text/html')
134
- get '/gridfs/stuff/187d/foo.html'
135
- assert_equal 'text/html', last_response.content_type
136
- end
137
-
138
130
  should "work for small images" do
139
- load_artifact('3wolfmoon.jpg', 'images/3wolfmoon.jpg', 'image/jpeg')
140
- get '/gridfs/images/3wolfmoon.jpg'
131
+ image_id = load_artifact('3wolfmoon.jpg', 'image/jpeg')
132
+ get "/gridfs/#{image_id}"
141
133
  assert last_response.ok?
142
134
  assert_equal 'image/jpeg', last_response.content_type
143
135
  end
data/test/test_helper.rb CHANGED
@@ -7,8 +7,13 @@ require 'rack/builder'
7
7
  require 'rack/mock'
8
8
  require 'rack/test'
9
9
 
10
- gem 'mongo', '>= 0.15.1'
11
-
12
10
  require 'mongo'
13
- require 'mongo/gridfs'
14
11
  require File.join(File.dirname(__FILE__), '..', 'lib', 'rack', 'gridfs')
12
+
13
+
14
+ class Hash
15
+ def except(*keys)
16
+ rejected = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
17
+ reject { |key,| rejected.include?(key) }
18
+ end
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-gridfs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blake Carlson
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-19 00:00:00 -04:00
12
+ date: 2010-05-11 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,25 +22,15 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: "0"
24
24
  version:
25
- - !ruby/object:Gem::Dependency
26
- name: activesupport
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: "0"
34
- version:
35
25
  - !ruby/object:Gem::Dependency
36
26
  name: mongo
37
27
  type: :runtime
38
28
  version_requirement:
39
29
  version_requirements: !ruby/object:Gem::Requirement
40
30
  requirements:
41
- - - "="
31
+ - - ">="
42
32
  - !ruby/object:Gem::Version
43
- version: 0.15.1
33
+ version: 0.20.1
44
34
  version:
45
35
  - !ruby/object:Gem::Dependency
46
36
  name: mocha
@@ -63,7 +53,7 @@ dependencies:
63
53
  version: "0"
64
54
  version:
65
55
  - !ruby/object:Gem::Dependency
66
- name: thoughtbot-shoulda
56
+ name: shoulda
67
57
  type: :development
68
58
  version_requirement:
69
59
  version_requirements: !ruby/object:Gem::Requirement