rack-gridfs 0.2.0 → 0.3.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.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