fog-dragonfly 0.8.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.
Files changed (155) hide show
  1. data/.specopts +2 -0
  2. data/.yardopts +23 -0
  3. data/Gemfile +23 -0
  4. data/Gemfile.rails.2.3.5 +14 -0
  5. data/History.md +266 -0
  6. data/LICENSE +20 -0
  7. data/README.md +88 -0
  8. data/Rakefile +92 -0
  9. data/VERSION +1 -0
  10. data/config.ru +13 -0
  11. data/docs.watchr +1 -0
  12. data/dragonfly.gemspec +293 -0
  13. data/extra_docs/Analysers.md +108 -0
  14. data/extra_docs/Caching.md +23 -0
  15. data/extra_docs/Configuration.md +138 -0
  16. data/extra_docs/DataStorage.md +136 -0
  17. data/extra_docs/Encoding.md +96 -0
  18. data/extra_docs/GeneralUsage.md +121 -0
  19. data/extra_docs/Generators.md +102 -0
  20. data/extra_docs/Heroku.md +50 -0
  21. data/extra_docs/Index.md +36 -0
  22. data/extra_docs/MimeTypes.md +40 -0
  23. data/extra_docs/Models.md +266 -0
  24. data/extra_docs/Mongo.md +45 -0
  25. data/extra_docs/Processing.md +130 -0
  26. data/extra_docs/Rack.md +52 -0
  27. data/extra_docs/Rails2.md +55 -0
  28. data/extra_docs/Rails3.md +62 -0
  29. data/extra_docs/Sinatra.md +25 -0
  30. data/extra_docs/URLs.md +169 -0
  31. data/features/3.0.3.feature +8 -0
  32. data/features/images.feature +47 -0
  33. data/features/no_processing.feature +14 -0
  34. data/features/rails_2.3.5.feature +7 -0
  35. data/features/steps/common_steps.rb +8 -0
  36. data/features/steps/dragonfly_steps.rb +66 -0
  37. data/features/steps/rails_steps.rb +39 -0
  38. data/features/support/env.rb +40 -0
  39. data/fixtures/files/app/models/album.rb +3 -0
  40. data/fixtures/files/app/views/albums/new.html.erb +4 -0
  41. data/fixtures/files/app/views/albums/show.html.erb +4 -0
  42. data/fixtures/files/config/initializers/dragonfly.rb +4 -0
  43. data/fixtures/files/features/manage_album_images.feature +12 -0
  44. data/fixtures/files/features/step_definitions/image_steps.rb +15 -0
  45. data/fixtures/files/features/support/paths.rb +15 -0
  46. data/fixtures/files/features/text_images.feature +7 -0
  47. data/fixtures/rails_2.3.5/template.rb +10 -0
  48. data/fixtures/rails_3.0.3/template.rb +20 -0
  49. data/irbrc.rb +17 -0
  50. data/lib/dragonfly.rb +45 -0
  51. data/lib/dragonfly/active_model_extensions.rb +13 -0
  52. data/lib/dragonfly/active_model_extensions/attachment.rb +169 -0
  53. data/lib/dragonfly/active_model_extensions/class_methods.rb +45 -0
  54. data/lib/dragonfly/active_model_extensions/instance_methods.rb +28 -0
  55. data/lib/dragonfly/active_model_extensions/validations.rb +37 -0
  56. data/lib/dragonfly/analyser.rb +59 -0
  57. data/lib/dragonfly/analysis/file_command_analyser.rb +32 -0
  58. data/lib/dragonfly/analysis/image_magick_analyser.rb +47 -0
  59. data/lib/dragonfly/analysis/r_magick_analyser.rb +63 -0
  60. data/lib/dragonfly/app.rb +182 -0
  61. data/lib/dragonfly/config/heroku.rb +19 -0
  62. data/lib/dragonfly/config/image_magick.rb +41 -0
  63. data/lib/dragonfly/config/r_magick.rb +46 -0
  64. data/lib/dragonfly/config/rails.rb +17 -0
  65. data/lib/dragonfly/configurable.rb +119 -0
  66. data/lib/dragonfly/core_ext/object.rb +8 -0
  67. data/lib/dragonfly/core_ext/string.rb +9 -0
  68. data/lib/dragonfly/core_ext/symbol.rb +9 -0
  69. data/lib/dragonfly/data_storage.rb +9 -0
  70. data/lib/dragonfly/data_storage/file_data_store.rb +114 -0
  71. data/lib/dragonfly/data_storage/mongo_data_store.rb +82 -0
  72. data/lib/dragonfly/data_storage/s3data_store.rb +115 -0
  73. data/lib/dragonfly/encoder.rb +13 -0
  74. data/lib/dragonfly/encoding/image_magick_encoder.rb +57 -0
  75. data/lib/dragonfly/encoding/r_magick_encoder.rb +61 -0
  76. data/lib/dragonfly/function_manager.rb +69 -0
  77. data/lib/dragonfly/generation/hash_with_css_style_keys.rb +23 -0
  78. data/lib/dragonfly/generation/image_magick_generator.rb +140 -0
  79. data/lib/dragonfly/generation/r_magick_generator.rb +155 -0
  80. data/lib/dragonfly/generator.rb +9 -0
  81. data/lib/dragonfly/image_magick_utils.rb +81 -0
  82. data/lib/dragonfly/job.rb +371 -0
  83. data/lib/dragonfly/job_builder.rb +39 -0
  84. data/lib/dragonfly/job_definitions.rb +26 -0
  85. data/lib/dragonfly/job_endpoint.rb +15 -0
  86. data/lib/dragonfly/loggable.rb +28 -0
  87. data/lib/dragonfly/middleware.rb +34 -0
  88. data/lib/dragonfly/processing/image_magick_processor.rb +99 -0
  89. data/lib/dragonfly/processing/r_magick_processor.rb +126 -0
  90. data/lib/dragonfly/processor.rb +9 -0
  91. data/lib/dragonfly/r_magick_utils.rb +48 -0
  92. data/lib/dragonfly/rails/images.rb +22 -0
  93. data/lib/dragonfly/response.rb +82 -0
  94. data/lib/dragonfly/routed_endpoint.rb +40 -0
  95. data/lib/dragonfly/serializer.rb +32 -0
  96. data/lib/dragonfly/simple_cache.rb +23 -0
  97. data/lib/dragonfly/simple_endpoint.rb +63 -0
  98. data/lib/dragonfly/temp_object.rb +220 -0
  99. data/samples/beach.png +0 -0
  100. data/samples/egg.png +0 -0
  101. data/samples/round.gif +0 -0
  102. data/samples/sample.docx +0 -0
  103. data/samples/taj.jpg +0 -0
  104. data/spec/argument_matchers.rb +19 -0
  105. data/spec/dragonfly/active_model_extensions/active_model_setup.rb +97 -0
  106. data/spec/dragonfly/active_model_extensions/active_record_setup.rb +85 -0
  107. data/spec/dragonfly/active_model_extensions/model_spec.rb +723 -0
  108. data/spec/dragonfly/active_model_extensions/spec_helper.rb +11 -0
  109. data/spec/dragonfly/analyser_spec.rb +123 -0
  110. data/spec/dragonfly/analysis/file_command_analyser_spec.rb +57 -0
  111. data/spec/dragonfly/analysis/image_magick_analyser_spec.rb +15 -0
  112. data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +27 -0
  113. data/spec/dragonfly/analysis/shared_analyser_spec.rb +51 -0
  114. data/spec/dragonfly/app_spec.rb +280 -0
  115. data/spec/dragonfly/config/r_magick_spec.rb +25 -0
  116. data/spec/dragonfly/configurable_spec.rb +220 -0
  117. data/spec/dragonfly/core_ext/string_spec.rb +17 -0
  118. data/spec/dragonfly/core_ext/symbol_spec.rb +17 -0
  119. data/spec/dragonfly/data_storage/data_store_spec.rb +76 -0
  120. data/spec/dragonfly/data_storage/file_data_store_spec.rb +169 -0
  121. data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +38 -0
  122. data/spec/dragonfly/data_storage/s3_data_store_spec.rb +94 -0
  123. data/spec/dragonfly/deprecation_spec.rb +20 -0
  124. data/spec/dragonfly/encoding/image_magick_encoder_spec.rb +41 -0
  125. data/spec/dragonfly/encoding/r_magick_encoder_spec.rb +37 -0
  126. data/spec/dragonfly/function_manager_spec.rb +154 -0
  127. data/spec/dragonfly/generation/hash_with_css_style_keys_spec.rb +24 -0
  128. data/spec/dragonfly/generation/image_magick_generator_spec.rb +12 -0
  129. data/spec/dragonfly/generation/r_magick_generator_spec.rb +24 -0
  130. data/spec/dragonfly/generation/shared_generator_spec.rb +91 -0
  131. data/spec/dragonfly/image_magick_utils_spec.rb +16 -0
  132. data/spec/dragonfly/job_builder_spec.rb +37 -0
  133. data/spec/dragonfly/job_definitions_spec.rb +35 -0
  134. data/spec/dragonfly/job_endpoint_spec.rb +120 -0
  135. data/spec/dragonfly/job_spec.rb +773 -0
  136. data/spec/dragonfly/loggable_spec.rb +80 -0
  137. data/spec/dragonfly/middleware_spec.rb +68 -0
  138. data/spec/dragonfly/processing/image_magick_processor_spec.rb +29 -0
  139. data/spec/dragonfly/processing/r_magick_processor_spec.rb +26 -0
  140. data/spec/dragonfly/processing/shared_processing_spec.rb +215 -0
  141. data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
  142. data/spec/dragonfly/serializer_spec.rb +61 -0
  143. data/spec/dragonfly/simple_cache_spec.rb +27 -0
  144. data/spec/dragonfly/simple_endpoint_spec.rb +89 -0
  145. data/spec/dragonfly/temp_object_spec.rb +352 -0
  146. data/spec/image_matchers.rb +47 -0
  147. data/spec/simple_matchers.rb +44 -0
  148. data/spec/spec_helper.rb +58 -0
  149. data/yard/handlers/configurable_attr_handler.rb +38 -0
  150. data/yard/setup.rb +15 -0
  151. data/yard/templates/default/fulldoc/html/css/common.css +107 -0
  152. data/yard/templates/default/layout/html/layout.erb +87 -0
  153. data/yard/templates/default/module/html/configuration_summary.erb +31 -0
  154. data/yard/templates/default/module/setup.rb +17 -0
  155. metadata +550 -0
@@ -0,0 +1,19 @@
1
+ module Dragonfly
2
+ module Config
3
+
4
+ module Heroku
5
+
6
+ def self.apply_configuration(app, bucket_name)
7
+ app.configure do |c|
8
+ c.datastore = Dragonfly::DataStorage::S3DataStore.new
9
+ c.datastore.configure do |d|
10
+ d.bucket_name = bucket_name
11
+ d.access_key_id = ENV['S3_KEY'] || raise("ENV variable 'S3_KEY' needs to be set - use\n\theroku config:add S3_KEY=XXXXXXXXX")
12
+ d.secret_access_key = ENV['S3_SECRET'] || raise("ENV variable 'S3_SECRET' needs to be set - use\n\theroku config:add S3_SECRET=XXXXXXXXX")
13
+ end
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,41 @@
1
+ module Dragonfly
2
+ module Config
3
+
4
+ # ImageMagick is a saved configuration for Dragonfly apps, which does the following:
5
+ # - registers an imagemagick analyser
6
+ # - registers an imagemagick processor
7
+ # - registers an imagemagick encoder
8
+ # - adds thumb shortcuts like '280x140!', etc.
9
+ # Look at the source code for apply_configuration to see exactly how it configures the app.
10
+ module ImageMagick
11
+
12
+ def self.apply_configuration(app, opts={})
13
+ app.configure do |c|
14
+ c.analyser.register(Analysis::ImageMagickAnalyser)
15
+ c.processor.register(Processing::ImageMagickProcessor)
16
+ c.encoder.register(Encoding::ImageMagickEncoder)
17
+ c.generator.register(Generation::ImageMagickGenerator)
18
+
19
+ c.job :thumb do |geometry, format|
20
+ process :thumb, geometry
21
+ encode format if format
22
+ end
23
+ c.job :gif do
24
+ encode :gif
25
+ end
26
+ c.job :jpg do
27
+ encode :jpg
28
+ end
29
+ c.job :png do
30
+ encode :png
31
+ end
32
+ c.job :convert do |args, format|
33
+ process :convert, args, format
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,46 @@
1
+ module Dragonfly
2
+ module Config
3
+
4
+ # RMagick is a saved configuration for Dragonfly apps, which does the following:
5
+ # - registers an rmagick analyser
6
+ # - registers an rmagick processor
7
+ # - registers an rmagick encoder
8
+ # - adds thumb shortcuts like '280x140!', etc.
9
+ # Look at the source code for apply_configuration to see exactly how it configures the app.
10
+ module RMagick
11
+
12
+ def self.apply_configuration(app, opts={})
13
+ use_filesystem = opts.has_key?(:use_filesystem) ? opts[:use_filesystem] : true
14
+ app.configure do |c|
15
+ c.analyser.register(Analysis::RMagickAnalyser) do |a|
16
+ a.use_filesystem = use_filesystem
17
+ end
18
+ c.processor.register(Processing::RMagickProcessor) do |p|
19
+ p.use_filesystem = use_filesystem
20
+ end
21
+ c.encoder.register(Encoding::RMagickEncoder) do |e|
22
+ e.use_filesystem = use_filesystem
23
+ end
24
+ c.generator.register(Generation::RMagickGenerator) do |g|
25
+ g.use_filesystem = use_filesystem
26
+ end
27
+ c.job :thumb do |geometry, format|
28
+ process :thumb, geometry
29
+ encode format if format
30
+ end
31
+ c.job :gif do
32
+ encode :gif
33
+ end
34
+ c.job :jpg do
35
+ encode :jpg
36
+ end
37
+ c.job :png do
38
+ encode :png
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,17 @@
1
+ module Dragonfly
2
+ module Config
3
+
4
+ module Rails
5
+
6
+ def self.apply_configuration(app)
7
+ app.configure do |c|
8
+ c.log = ::Rails.logger
9
+ c.datastore.root_path = "#{::Rails.root}/public/system/dragonfly/#{::Rails.env}" if c.datastore.is_a?(DataStorage::FileDataStore)
10
+ c.url_path_prefix = '/media'
11
+ c.analyser.register(Analysis::FileCommandAnalyser)
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,119 @@
1
+ module Dragonfly
2
+ module Configurable
3
+
4
+ # Exceptions
5
+ class BadConfigAttribute < StandardError; end
6
+
7
+ def self.included(klass)
8
+ klass.class_eval do
9
+ include Configurable::InstanceMethods
10
+ extend Configurable::ClassMethods
11
+
12
+ # These aren't included in InstanceMethods because we need access to 'klass'
13
+ # We can't just put them into InstanceMethods and use 'self.class' because
14
+ # this won't always point to the class in which we've included Configurable,
15
+ # e.g. if we've included it in an eigenclasse
16
+ define_method :configuration_hash do
17
+ @configuration_hash ||= klass.default_configuration.dup
18
+ end
19
+ private :configuration_hash
20
+
21
+ define_method :configuration_methods do
22
+ klass.configuration_methods
23
+ end
24
+
25
+ end
26
+ end
27
+
28
+ class DeferredBlock < Proc; end
29
+
30
+ module InstanceMethods
31
+
32
+ def configure(&block)
33
+ yield ConfigurationProxy.new(self)
34
+ self
35
+ end
36
+
37
+ def configure_with(configurer, *args, &block)
38
+ configurer = configurer_for(configurer) if configurer.is_a?(Symbol)
39
+ configurer.apply_configuration(self, *args)
40
+ configure(&block) if block
41
+ self
42
+ end
43
+
44
+ def configuration
45
+ configuration_hash.dup
46
+ end
47
+
48
+ def has_configuration_method?(method_name)
49
+ configuration_methods.include?(method_name.to_sym)
50
+ end
51
+
52
+ end
53
+
54
+ module ClassMethods
55
+
56
+ def default_configuration
57
+ @default_configuration ||= {}
58
+ end
59
+
60
+ def configuration_methods
61
+ @configuration_methods ||= []
62
+ end
63
+
64
+ private
65
+
66
+ def configurable_attr attribute, default=nil, &blk
67
+ default_configuration[attribute] = blk ? DeferredBlock.new(&blk) : default
68
+
69
+ # Define the reader
70
+ define_method(attribute) do
71
+ if configuration_hash[attribute].is_a?(DeferredBlock)
72
+ configuration_hash[attribute] = configuration_hash[attribute].call
73
+ end
74
+ configuration_hash[attribute]
75
+ end
76
+
77
+ # Define the writer
78
+ define_method("#{attribute}=") do |value|
79
+ configuration_hash[attribute] = value
80
+ end
81
+
82
+ configuration_method attribute
83
+ configuration_method "#{attribute}="
84
+ end
85
+
86
+ def configuration_method(*method_names)
87
+ configuration_methods.push(*method_names.map{|n| n.to_sym })
88
+ end
89
+
90
+ end
91
+
92
+ class ConfigurationProxy
93
+
94
+ def initialize(owner)
95
+ @owner = owner
96
+ end
97
+
98
+ def method_missing(method_name, *args, &block)
99
+ if owner.has_configuration_method?(method_name)
100
+ owner.send(method_name, *args, &block)
101
+ elsif nested_configurable?(method_name, *args)
102
+ owner.send(method_name, *args)
103
+ else
104
+ raise BadConfigAttribute, "You tried to configure using '#{method_name.inspect}', but the valid config attributes are #{owner.configuration_methods.map{|a| %('#{a.inspect}') }.sort.join(', ')}"
105
+ end
106
+ end
107
+
108
+ private
109
+
110
+ attr_reader :owner
111
+
112
+ def nested_configurable?(method, *args)
113
+ owner.respond_to?(method) && owner.send(method, *args).is_a?(Configurable)
114
+ end
115
+
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,8 @@
1
+ class Object
2
+
3
+ # Will eventually get this by cherry-picking from activesupport
4
+ def blank?
5
+ respond_to?(:empty?) ? empty? : !self
6
+ end
7
+
8
+ end
@@ -0,0 +1,9 @@
1
+ class String
2
+
3
+ # Ruby 1.8 reports methods as strings,
4
+ # whereas 1.9 reports them as symbols
5
+ def to_method_name
6
+ RUBY_VERSION =~ /^1.8/ ? self : to_sym
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ class Symbol
2
+
3
+ # Ruby 1.8 reports methods as strings,
4
+ # whereas 1.9 reports them as symbols
5
+ def to_method_name
6
+ RUBY_VERSION =~ /^1.8/ ? to_s : self
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ module Dragonfly
2
+ module DataStorage
3
+
4
+ # Exceptions
5
+ class DataNotFound < StandardError; end
6
+ class UnableToStore < StandardError; end
7
+
8
+ end
9
+ end
@@ -0,0 +1,114 @@
1
+ require 'pathname'
2
+
3
+ module Dragonfly
4
+ module DataStorage
5
+
6
+ class FileDataStore
7
+
8
+ include Configurable
9
+
10
+ configurable_attr :root_path, '/var/tmp/dragonfly'
11
+
12
+ def store(temp_object, opts={})
13
+ relative_path = if opts[:path]
14
+ opts[:path]
15
+ else
16
+ filename = temp_object.name || 'file'
17
+ relative_path = relative_path_for(filename)
18
+ end
19
+
20
+ begin
21
+ path = absolute(relative_path)
22
+ until !File.exist?(path)
23
+ path = disambiguate(path)
24
+ end
25
+ prepare_path(path)
26
+ temp_object.to_file(path).close
27
+ store_extra_data(path, temp_object)
28
+ rescue Errno::EACCES => e
29
+ raise UnableToStore, e.message
30
+ end
31
+
32
+ relative(path)
33
+ end
34
+
35
+ def retrieve(relative_path)
36
+ path = absolute(relative_path)
37
+ file = File.new(path)
38
+ file.close
39
+ [
40
+ file,
41
+ retrieve_extra_data(path)
42
+ ]
43
+ rescue Errno::ENOENT => e
44
+ raise DataNotFound, e.message
45
+ end
46
+
47
+ def destroy(relative_path)
48
+ path = absolute(relative_path)
49
+ FileUtils.rm path
50
+ FileUtils.rm extra_data_path(path)
51
+ purge_empty_directories(relative_path)
52
+ rescue Errno::ENOENT => e
53
+ raise DataNotFound, e.message
54
+ end
55
+
56
+ def disambiguate(path)
57
+ dirname = File.dirname(path)
58
+ basename = File.basename(path, '.*')
59
+ extname = File.extname(path)
60
+ "#{dirname}/#{basename}_#{Time.now.usec.to_s(32)}#{extname}"
61
+ end
62
+
63
+ private
64
+
65
+ def absolute(relative_path)
66
+ File.join(root_path, relative_path)
67
+ end
68
+
69
+ def relative(absolute_path)
70
+ absolute_path[/^#{root_path}\/?(.*)$/, 1]
71
+ end
72
+
73
+ def directory_empty?(path)
74
+ Dir.entries(path) == ['.','..']
75
+ end
76
+
77
+ def extra_data_path(data_path)
78
+ "#{data_path}.extra"
79
+ end
80
+
81
+ def relative_path_for(filename)
82
+ time = Time.now
83
+ msec = time.usec / 1000
84
+ "#{time.strftime '%Y/%m/%d/%H_%M_%S'}_#{msec}_#{filename.gsub(/[^\w.]+/,'_')}"
85
+ end
86
+
87
+ def store_extra_data(data_path, temp_object)
88
+ File.open(extra_data_path(data_path), 'wb') do |f|
89
+ f.write Marshal.dump(temp_object.attributes)
90
+ end
91
+ end
92
+
93
+ def retrieve_extra_data(data_path)
94
+ path = extra_data_path(data_path)
95
+ File.exist?(path) ? File.open(path,'rb'){|f| Marshal.load(f.read) } : {}
96
+ end
97
+
98
+ def prepare_path(path)
99
+ dir = File.dirname(path)
100
+ FileUtils.mkdir_p(dir) unless File.exist?(dir)
101
+ end
102
+
103
+ def purge_empty_directories(path)
104
+ containing_directory = Pathname.new(path).dirname
105
+ containing_directory.ascend do |relative_dir|
106
+ dir = absolute(relative_dir)
107
+ FileUtils.rmdir dir if directory_empty?(dir)
108
+ end
109
+ end
110
+
111
+ end
112
+
113
+ end
114
+ end
@@ -0,0 +1,82 @@
1
+ require 'mongo'
2
+
3
+ module Dragonfly
4
+ module DataStorage
5
+ class MongoDataStore
6
+
7
+ include Configurable
8
+ include Serializer
9
+
10
+ configurable_attr :host
11
+ configurable_attr :port
12
+ configurable_attr :database, 'dragonfly'
13
+ configurable_attr :username
14
+ configurable_attr :password
15
+
16
+ # Mongo gem deprecated ObjectID in favour of ObjectId
17
+ OBJECT_ID = defined?(BSON::ObjectId) ? BSON::ObjectId : BSON::ObjectID
18
+ INVALID_OBJECT_ID = defined?(BSON::InvalidObjectId) ? BSON::InvalidObjectId : BSON::InvalidObjectID
19
+
20
+ def initialize(opts={})
21
+ self.host = opts[:host]
22
+ self.port = opts[:port]
23
+ self.database = opts[:database] if opts[:database]
24
+ self.username = opts[:username]
25
+ self.password = opts[:password]
26
+ end
27
+
28
+ def store(temp_object, opts={})
29
+ ensure_authenticated!
30
+ temp_object.file do |f|
31
+ mongo_id = grid.put(f, :metadata => marshal_encode(temp_object.attributes))
32
+ mongo_id.to_s
33
+ end
34
+ end
35
+
36
+ def retrieve(uid)
37
+ ensure_authenticated!
38
+ grid_io = grid.get(bson_id(uid))
39
+ extra = marshal_decode(grid_io.metadata)
40
+ extra[:meta].merge!(:stored_at => grid_io.upload_date)
41
+ [
42
+ grid_io.read,
43
+ extra
44
+ ]
45
+ rescue Mongo::GridFileNotFound, INVALID_OBJECT_ID => e
46
+ raise DataNotFound, "#{e} - #{uid}"
47
+ end
48
+
49
+ def destroy(uid)
50
+ ensure_authenticated!
51
+ grid.delete(bson_id(uid))
52
+ rescue Mongo::GridFileNotFound, INVALID_OBJECT_ID => e
53
+ raise DataNotFound, "#{e} - #{uid}"
54
+ end
55
+
56
+ def connection
57
+ @connection ||= Mongo::Connection.new(host, port)
58
+ end
59
+
60
+ def db
61
+ @db ||= connection.db(database)
62
+ end
63
+
64
+ def grid
65
+ @grid ||= Mongo::Grid.new(db)
66
+ end
67
+
68
+ private
69
+
70
+ def ensure_authenticated!
71
+ if username
72
+ @authenticated ||= db.authenticate(username, password)
73
+ end
74
+ end
75
+
76
+ def bson_id(uid)
77
+ OBJECT_ID.from_string(uid)
78
+ end
79
+
80
+ end
81
+ end
82
+ end