dragonfly 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of dragonfly might be problematic. Click here for more details.

Files changed (157) hide show
  1. data/.gitignore +2 -0
  2. data/.specopts +2 -0
  3. data/.yardopts +11 -5
  4. data/Gemfile +22 -0
  5. data/Gemfile.rails.2.3.5 +13 -0
  6. data/History.md +49 -0
  7. data/README.md +18 -28
  8. data/Rakefile +24 -36
  9. data/VERSION +1 -1
  10. data/config.ru +4 -1
  11. data/dragonfly.gemspec +85 -99
  12. data/extra_docs/Analysers.md +66 -30
  13. data/extra_docs/Caching.md +22 -0
  14. data/extra_docs/Configuration.md +116 -0
  15. data/extra_docs/DataStorage.md +114 -14
  16. data/extra_docs/Encoding.md +62 -37
  17. data/extra_docs/GeneralUsage.md +118 -0
  18. data/extra_docs/Generators.md +92 -0
  19. data/extra_docs/Heroku.md +51 -0
  20. data/extra_docs/Index.md +8 -9
  21. data/extra_docs/MimeTypes.md +18 -17
  22. data/extra_docs/Models.md +251 -0
  23. data/extra_docs/Processing.md +94 -70
  24. data/extra_docs/Rack.md +53 -0
  25. data/extra_docs/Rails2.md +44 -0
  26. data/extra_docs/Rails3.md +51 -0
  27. data/extra_docs/Sinatra.md +21 -0
  28. data/extra_docs/URLs.md +114 -0
  29. data/features/images.feature +6 -7
  30. data/features/no_processing.feature +0 -6
  31. data/features/rails_2.3.5.feature +1 -1
  32. data/features/rails_3.0.0.rc.feature +8 -0
  33. data/features/steps/dragonfly_steps.rb +14 -12
  34. data/features/steps/rails_steps.rb +20 -9
  35. data/features/support/env.rb +10 -11
  36. data/fixtures/files/app/views/albums/new.html.erb +4 -4
  37. data/fixtures/files/app/views/albums/show.html.erb +1 -1
  38. data/fixtures/files/features/manage_album_images.feature +1 -1
  39. data/fixtures/files/features/step_definitions/{album_steps.rb → image_steps.rb} +4 -3
  40. data/fixtures/files/features/support/paths.rb +2 -0
  41. data/fixtures/files/features/text_images.feature +7 -0
  42. data/fixtures/rails_3.0.0.rc/template.rb +21 -0
  43. data/irbrc.rb +2 -1
  44. data/lib/dragonfly.rb +4 -16
  45. data/lib/dragonfly/{active_record_extensions.rb → active_model_extensions.rb} +1 -1
  46. data/lib/dragonfly/active_model_extensions/attachment.rb +146 -0
  47. data/lib/dragonfly/{active_record_extensions → active_model_extensions}/class_methods.rb +5 -6
  48. data/lib/dragonfly/{active_record_extensions → active_model_extensions}/instance_methods.rb +1 -1
  49. data/lib/dragonfly/{active_record_extensions → active_model_extensions}/validations.rb +5 -9
  50. data/lib/dragonfly/analyser.rb +59 -0
  51. data/lib/dragonfly/analysis/file_command_analyser.rb +1 -1
  52. data/lib/dragonfly/analysis/r_magick_analyser.rb +46 -31
  53. data/lib/dragonfly/app.rb +138 -173
  54. data/lib/dragonfly/config/heroku.rb +19 -0
  55. data/lib/dragonfly/config/r_magick.rb +37 -0
  56. data/lib/dragonfly/config/{rails_defaults.rb → rails.rb} +6 -7
  57. data/lib/dragonfly/configurable.rb +30 -27
  58. data/lib/dragonfly/core_ext/object.rb +1 -1
  59. data/lib/dragonfly/data_storage/file_data_store.rb +59 -26
  60. data/lib/dragonfly/data_storage/mongo_data_store.rb +65 -0
  61. data/lib/dragonfly/data_storage/s3data_store.rb +31 -12
  62. data/lib/dragonfly/encoder.rb +13 -0
  63. data/lib/dragonfly/encoding/r_magick_encoder.rb +10 -19
  64. data/lib/dragonfly/endpoint.rb +43 -0
  65. data/lib/dragonfly/function_manager.rb +65 -0
  66. data/lib/dragonfly/{processing/r_magick_text_processor.rb → generation/r_magick_generator.rb} +25 -11
  67. data/lib/dragonfly/generator.rb +9 -0
  68. data/lib/dragonfly/job.rb +290 -0
  69. data/lib/dragonfly/job_builder.rb +39 -0
  70. data/lib/dragonfly/job_definitions.rb +26 -0
  71. data/lib/dragonfly/job_endpoint.rb +17 -0
  72. data/lib/dragonfly/loggable.rb +28 -0
  73. data/lib/dragonfly/middleware.rb +21 -14
  74. data/lib/dragonfly/processing/r_magick_processor.rb +71 -48
  75. data/lib/dragonfly/processor.rb +9 -0
  76. data/lib/dragonfly/r_magick_utils.rb +24 -0
  77. data/lib/dragonfly/rails/images.rb +10 -7
  78. data/lib/dragonfly/routed_endpoint.rb +42 -0
  79. data/lib/dragonfly/serializer.rb +32 -0
  80. data/lib/dragonfly/simple_cache.rb +23 -0
  81. data/lib/dragonfly/simple_endpoint.rb +64 -0
  82. data/lib/dragonfly/temp_object.rb +77 -45
  83. data/spec/argument_matchers.rb +7 -17
  84. data/spec/dragonfly/active_model_extensions/active_model_setup.rb +97 -0
  85. data/spec/dragonfly/active_model_extensions/active_record_setup.rb +85 -0
  86. data/spec/dragonfly/{active_record_extensions → active_model_extensions}/model_spec.rb +282 -244
  87. data/spec/dragonfly/active_model_extensions/spec_helper.rb +11 -0
  88. data/spec/dragonfly/analyser_spec.rb +123 -0
  89. data/spec/dragonfly/analysis/file_command_analyser_spec.rb +2 -2
  90. data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +10 -1
  91. data/spec/dragonfly/app_spec.rb +175 -69
  92. data/spec/dragonfly/configurable_spec.rb +14 -0
  93. data/spec/dragonfly/data_storage/data_store_spec.rb +36 -9
  94. data/spec/dragonfly/data_storage/file_data_store_spec.rb +61 -38
  95. data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +18 -0
  96. data/spec/dragonfly/data_storage/s3_data_store_spec.rb +34 -39
  97. data/spec/dragonfly/deprecation_spec.rb +20 -0
  98. data/spec/dragonfly/function_manager_spec.rb +154 -0
  99. data/spec/dragonfly/generation/r_magick_generator_spec.rb +119 -0
  100. data/spec/dragonfly/job_builder_spec.rb +37 -0
  101. data/spec/dragonfly/job_definitions_spec.rb +35 -0
  102. data/spec/dragonfly/job_endpoint_spec.rb +66 -0
  103. data/spec/dragonfly/job_spec.rb +605 -0
  104. data/spec/dragonfly/loggable_spec.rb +80 -0
  105. data/spec/dragonfly/middleware_spec.rb +37 -17
  106. data/spec/dragonfly/processing/r_magick_processor_spec.rb +182 -166
  107. data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
  108. data/spec/dragonfly/serializer_spec.rb +61 -0
  109. data/spec/dragonfly/simple_cache_spec.rb +27 -0
  110. data/spec/dragonfly/simple_endpoint_spec.rb +78 -0
  111. data/spec/dragonfly/temp_object_spec.rb +154 -119
  112. data/spec/simple_matchers.rb +22 -0
  113. data/spec/spec_helper.rb +28 -4
  114. data/yard/templates/default/layout/html/layout.erb +18 -11
  115. metadata +89 -190
  116. data/config.rb +0 -5
  117. data/extra_docs/ActiveRecord.md +0 -196
  118. data/extra_docs/ExampleUseCases.md +0 -189
  119. data/extra_docs/GettingStarted.md +0 -114
  120. data/extra_docs/Shortcuts.md +0 -118
  121. data/extra_docs/UsingWithRails.md +0 -81
  122. data/features/rails_3.0.0.beta3.feature +0 -7
  123. data/fixtures/rails_3.0.0.beta3/template.rb +0 -16
  124. data/lib/dragonfly/active_record_extensions/attachment.rb +0 -170
  125. data/lib/dragonfly/analyser_list.rb +0 -9
  126. data/lib/dragonfly/analysis/base.rb +0 -10
  127. data/lib/dragonfly/belongs_to_app.rb +0 -24
  128. data/lib/dragonfly/config/heroku_rails_images.rb +0 -23
  129. data/lib/dragonfly/config/r_magick_images.rb +0 -69
  130. data/lib/dragonfly/config/r_magick_text.rb +0 -25
  131. data/lib/dragonfly/config/rails_images.rb +0 -13
  132. data/lib/dragonfly/data_storage/base.rb +0 -21
  133. data/lib/dragonfly/data_storage/base64_data_store.rb +0 -23
  134. data/lib/dragonfly/data_storage/transparent_data_store.rb +0 -21
  135. data/lib/dragonfly/delegatable.rb +0 -14
  136. data/lib/dragonfly/delegator.rb +0 -62
  137. data/lib/dragonfly/encoder_list.rb +0 -9
  138. data/lib/dragonfly/encoding/base.rb +0 -14
  139. data/lib/dragonfly/encoding/transparent_encoder.rb +0 -14
  140. data/lib/dragonfly/extended_temp_object.rb +0 -120
  141. data/lib/dragonfly/parameters.rb +0 -163
  142. data/lib/dragonfly/processing/base.rb +0 -10
  143. data/lib/dragonfly/processor_list.rb +0 -9
  144. data/lib/dragonfly/url_handler.rb +0 -147
  145. data/spec/dragonfly/active_record_extensions/attachment_spec.rb +0 -8
  146. data/spec/dragonfly/active_record_extensions/migration.rb +0 -42
  147. data/spec/dragonfly/active_record_extensions/models.rb +0 -6
  148. data/spec/dragonfly/active_record_extensions/spec_helper.rb +0 -24
  149. data/spec/dragonfly/belongs_to_app_spec.rb +0 -55
  150. data/spec/dragonfly/delegatable_spec.rb +0 -32
  151. data/spec/dragonfly/delegator_spec.rb +0 -145
  152. data/spec/dragonfly/extended_temp_object_spec.rb +0 -71
  153. data/spec/dragonfly/parameters_spec.rb +0 -298
  154. data/spec/dragonfly/processing/r_magick_text_processor_spec.rb +0 -84
  155. data/spec/dragonfly/url_handler_spec.rb +0 -247
  156. data/spec/dragonfly_spec.rb +0 -16
  157. data/spec/ginger_scenarios.rb +0 -13
@@ -1,16 +1,15 @@
1
1
  module Dragonfly
2
- module ActiveRecordExtensions
2
+ module ActiveModelExtensions
3
3
  module ClassMethods
4
4
 
5
5
  include Validations
6
6
 
7
- def register_dragonfly_app(accessor_prefix, app)
8
- eigenclass = respond_to?(:metaclass) ? metaclass : singleton_class # Because rails changed the name from metaclass -> singleton_class
9
- eigenclass.class_eval do
7
+ def register_dragonfly_app(macro_name, app)
8
+ (class << self; self; end).class_eval do
10
9
 
11
10
  # Defines e.g. 'image_accessor' for any activerecord class body
12
- define_method "#{accessor_prefix}_accessor" do |attribute|
13
-
11
+ define_method macro_name do |attribute|
12
+
14
13
  # Prior to activerecord 3, adding before callbacks more than once does add it more than once
15
14
  before_save :save_attachments unless respond_to?(:before_save_callback_chain) && before_save_callback_chain.find(:save_attachments)
16
15
  before_destroy :destroy_attachments unless respond_to?(:before_destroy_callback_chain) && before_destroy_callback_chain.find(:destroy_attachments)
@@ -1,5 +1,5 @@
1
1
  module Dragonfly
2
- module ActiveRecordExtensions
2
+ module ActiveModelExtensions
3
3
  module InstanceMethods
4
4
 
5
5
  def attachments
@@ -1,16 +1,16 @@
1
1
  module Dragonfly
2
- module ActiveRecordExtensions
2
+ module ActiveModelExtensions
3
3
  module Validations
4
-
4
+
5
5
  private
6
-
6
+
7
7
  def validates_property(property_name, opts)
8
8
  attrs = opts[:of] or raise ArgumentError, "you need to provide the attribute which has the property, using :of => <attribute_name>"
9
9
  attrs = [attrs].flatten #(make sure it's an array)
10
10
 
11
11
  raise ArgumentError, "you must provide either :in => [<value1>, <value2>..] or :as => <value>" unless opts[:in] || opts[:as]
12
12
  allowed_values = opts[:in] || [opts[:as]]
13
-
13
+
14
14
  args = attrs + [opts]
15
15
  validates_each(*args) do |record, attr, attachment|
16
16
  if attachment
@@ -23,11 +23,7 @@ module Dragonfly
23
23
  end
24
24
 
25
25
  end
26
-
27
- def validates_mime_type_of(attribute, opts)
28
- validates_property :mime_type, opts.merge(:of => attribute)
29
- end
30
-
26
+
31
27
  def expected_values_string(allowed_values)
32
28
  if allowed_values.is_a?(Range)
33
29
  "between #{allowed_values.first} and #{allowed_values.last}"
@@ -0,0 +1,59 @@
1
+ module Dragonfly
2
+ class Analyser < FunctionManager
3
+
4
+ include Configurable
5
+ configurable_attr :enable_cache, true
6
+ configurable_attr :cache_size, 100
7
+
8
+ def initialize
9
+ super
10
+ analyser = self
11
+ @analysis_methods = Module.new do
12
+
13
+ define_method :analyser do
14
+ analyser
15
+ end
16
+
17
+ end
18
+ @analysis_method_names = []
19
+ end
20
+
21
+ attr_reader :analysis_methods, :analysis_method_names
22
+
23
+ def analyse(temp_object, method, *args)
24
+ if enable_cache
25
+ key = [temp_object.object_id, method, *args]
26
+ cache[key] ||= call_last(method, temp_object, *args)
27
+ else
28
+ call_last(method, temp_object, *args)
29
+ end
30
+ rescue NotDefined, UnableToHandle => e
31
+ log.warn(e.message)
32
+ nil
33
+ end
34
+
35
+ # Each time a function is registered with the analyser,
36
+ # add a method to the analysis_methods module.
37
+ # Expects the object that is extended to define 'analyse(method, *args)'
38
+ def add(name, *args, &block)
39
+ analysis_methods.module_eval %(
40
+ def #{name}(*args)
41
+ analyse(:#{name}, *args)
42
+ end
43
+ )
44
+ analysis_method_names << name.to_sym
45
+ super
46
+ end
47
+
48
+ def clear_cache!
49
+ @cache = nil
50
+ end
51
+
52
+ private
53
+
54
+ def cache
55
+ @cache ||= SimpleCache.new(cache_size)
56
+ end
57
+
58
+ end
59
+ end
@@ -1,7 +1,7 @@
1
1
  module Dragonfly
2
2
  module Analysis
3
3
 
4
- class FileCommandAnalyser < Base
4
+ class FileCommandAnalyser
5
5
 
6
6
  include Configurable
7
7
 
@@ -2,45 +2,60 @@ require 'RMagick'
2
2
 
3
3
  module Dragonfly
4
4
  module Analysis
5
-
6
- class RMagickAnalyser < Base
7
-
8
- def width(image)
9
- rmagick_image(image).columns
5
+ class RMagickAnalyser
6
+
7
+ include Loggable
8
+ include RMagickUtils
9
+
10
+ def width(temp_object)
11
+ rmagick_image(temp_object) do |image|
12
+ image.columns
13
+ end
14
+ end
15
+
16
+ def height(temp_object)
17
+ rmagick_image(temp_object) do |image|
18
+ image.rows
19
+ end
20
+ end
21
+
22
+ def aspect_ratio(temp_object)
23
+ rmagick_image(temp_object) do |image|
24
+ image.columns.to_f / image.rows
25
+ end
10
26
  end
11
-
12
- def height(image)
13
- rmagick_image(image).rows
27
+
28
+ def portrait?(temp_object)
29
+ rmagick_image(temp_object) do |image|
30
+ image.columns <= image.rows
31
+ end
14
32
  end
15
-
16
- def aspect_ratio(image)
17
- rmagick_data = rmagick_image(image)
18
- rmagick_data.columns.to_f / rmagick_data.rows
33
+
34
+ def landscape?(temp_object)
35
+ rmagick_image(temp_object) do |image|
36
+ image.columns >= image.rows
37
+ end
19
38
  end
20
-
21
- def depth(image)
22
- rmagick_image(image).depth
39
+
40
+ def depth(temp_object)
41
+ rmagick_image(temp_object) do |image|
42
+ image.depth
43
+ end
23
44
  end
24
-
25
- def number_of_colours(image)
26
- rmagick_image(image).number_colors
45
+
46
+ def number_of_colours(temp_object)
47
+ rmagick_image(temp_object) do |image|
48
+ image.number_colors
49
+ end
27
50
  end
28
51
  alias number_of_colors number_of_colours
29
52
 
30
- def format(image)
31
- rmagick_image(image).format.downcase.to_sym
32
- end
33
-
34
- private
35
-
36
- def rmagick_image(image)
37
- Magick::Image.from_blob(image.data).first
38
- rescue Magick::ImageMagickError => e
39
- log.warn("Unable to handle content in #{self.class} - got:\n#{e}")
40
- throw :unable_to_handle
53
+ def format(temp_object)
54
+ rmagick_image(temp_object) do |image|
55
+ image.format.downcase.to_sym
56
+ end
41
57
  end
42
-
58
+
43
59
  end
44
-
45
60
  end
46
61
  end
data/lib/dragonfly/app.rb CHANGED
@@ -1,193 +1,101 @@
1
1
  require 'logger'
2
2
  require 'forwardable'
3
+ require 'rack'
3
4
 
4
5
  module Dragonfly
5
-
6
- # A Dragonfly App is the rack app which holds everything together.
7
- # You can have as many app instances as you want, and they all have
8
- # completely separate configuration.
9
- # Each App has a name.
10
- # @example
11
- # Dragonfly::App[:images] # => creates a new app named :images
12
- # Dragonfly::App[:images] # => returns the :images app
13
- # Dragonfly::App[:ocr] # => creates a new app named :ocr
14
- #
15
- # # The two apps can be differently configured
16
- # Dragonfly::App[:images].parameters.default_format = :jpg
17
- # Dragonfly::App[:ocr].parameters.default_format = :tif
18
- #
19
- # @example Example configuration options:
20
- #
21
- # Dragonfly::App[:images].configure do |c|
22
- # c.datastore = MyEC2DataStore.new # See DataStorage::Base for how to create a custom data store
23
- # c.register_analyser(Analysis::RMagickAnalyser) # See Analysis::Base for how to create a custom analyser
24
- # c.register_processor(Processing::RMagickProcessor) # See Processing::Base for how to create a custom analyser
25
- # c.register_encoder(Encoding::RMagickEncoder) # See Encoding::Base for how to create a custom encoder
26
- # c.log = Logger.new('/tmp/my.log')
27
- # c.cache_duration = 3000 # seconds
28
- # end
29
- #
30
- # @example Configuration including nested items
31
- #
32
- # Dragonfly::App[:images].configure do |c|
33
- # # ...
34
- # c.datastore.configure do |d| # configuration depends on which data store you use
35
- # # ...
36
- # end
37
- # c.parameters.configure do |p| # see Parameters (class methods)
38
- # # ...
39
- # end
40
- # c.url_handler.configure do |u| # see UrlHandler
41
- # # ...
42
- # end
43
- # end
44
- #
45
6
  class App
46
-
47
-
7
+
48
8
  class << self
49
-
9
+
50
10
  private :new # Hide 'new' - need to use 'instance'
51
-
52
- # Get / create a Dragonfly App.
53
- #
54
- # Rather than using 'new', use this method to create / refer to each app.
55
- #
56
- # @param [Symbol] name the name of the App
57
- # @return [App] either the named App or a new one with that name
11
+
58
12
  def instance(name)
59
13
  apps[name] ||= new
60
14
  end
61
-
15
+
62
16
  alias [] instance
63
-
17
+
64
18
  private
65
-
19
+
66
20
  def apps
67
21
  @apps ||= {}
68
22
  end
69
-
23
+
70
24
  end
71
-
25
+
72
26
  def initialize
73
- @analysers, @processors, @encoders = AnalyserList.new(self), ProcessorList.new(self), EncoderList.new(self)
74
- @parameters_class = Class.new(Parameters)
75
- @url_handler = UrlHandler.new(@parameters_class)
76
- end
77
-
78
- # @see Analysis::AnalyserList
79
- attr_reader :analysers
80
- # @see Processing::ProcessorList
81
- attr_reader :processors
82
- # @see Encoding::EncoderList
83
- attr_reader :encoders
84
- # @see UrlHandler
85
- attr_reader :url_handler
86
- # @see Parameters
87
- attr_reader :parameters_class
88
-
89
- alias parameters parameters_class
90
-
27
+ @analyser, @processor, @encoder, @generator = Analyser.new, Processor.new, Encoder.new, Generator.new
28
+ @analyser.use_same_log_as(self)
29
+ @processor.use_same_log_as(self)
30
+ @encoder.use_same_log_as(self)
31
+ @generator.use_same_log_as(self)
32
+ @job_definitions = JobDefinitions.new
33
+ @server = Dragonfly::SimpleEndpoint.new(self)
34
+ end
35
+
36
+ include Configurable
37
+
91
38
  extend Forwardable
92
- def_delegator :url_handler, :url_for
93
39
  def_delegator :datastore, :destroy
94
-
95
- include Configurable
96
-
40
+ def_delegators :new_job, :fetch, :generate, :fetch_file
41
+ def_delegator :server, :call
42
+
97
43
  configurable_attr :datastore do DataStorage::FileDataStore.new end
98
- configurable_attr :log do Logger.new('/var/tmp/dragonfly.log') end
99
44
  configurable_attr :cache_duration, 3600*24*365 # (1 year)
100
- configurable_attr :fallback_mime_type, 'application/octet-stream'
101
-
102
- # The call method required by Rack to run.
103
- #
104
- # @param env the Rack env hash
105
- # @return [Array] a Rack response:
106
- #
107
- # - 200 status if all ok
108
- #
109
- # - 400 if url recognised but parameters incorrect
110
- #
111
- # - 404 if url not recognised / data not found.
112
- #
113
- # See the Rack documentation for more details
114
- def call(env)
115
- parameters = url_handler.url_to_parameters(env['PATH_INFO'], env['QUERY_STRING'])
116
- temp_object = fetch(parameters.uid, parameters)
117
- [200, {
118
- "Content-Type" => mime_type_for(parameters.format, temp_object),
119
- "Content-Length" => temp_object.size.to_s,
120
- "ETag" => parameters.unique_signature,
121
- "Cache-Control" => "public, max-age=#{cache_duration}"
122
- }, temp_object]
123
- rescue UrlHandler::IncorrectSHA, UrlHandler::SHANotGiven => e
124
- warn_with_info(e.message, env)
125
- [400, {"Content-Type" => "text/plain"}, [e.message]]
126
- rescue UrlHandler::UnknownUrl, DataStorage::DataNotFound => e
127
- [404, {"Content-Type" => 'text/plain'}, [e.message]]
128
- end
129
-
130
- # Create a temp_object from the object passed in
131
- # @param [String, File, Tempfile, TempObject] initialization_object the object holding the data
132
- # @return [ExtendedTempObject] a temp_object holding the data
133
- def create_object(initialization_object)
134
- ExtendedTempObject.new(initialization_object, self)
135
- end
136
-
137
- # Fetch an object from the database and optionally transform
138
- #
139
- # Note that the arguments passed in to transform are as defined by the
140
- # parameter shortcuts (see Parameter class methods)
141
- # @param [String] uid the string uid corresponding to the stored data object
142
- # @param [*args [optional]] shortcut_args the shortcut args for transforming the object
143
- # @return [ExtendedTempObject] a temp_object holding the data
144
- # @example
145
- # app = Dragonfly::App[:images]
146
- # app.fetch('abcd1234') # returns a temp_object with exactly the data that was originally stored
147
- # app.fetch('abcd1234', '20x20!') # returns a transformed temp_object, in this case with image data resized to 20x20
148
- # @see Parameters
149
- def fetch(uid, *args)
150
- temp_object = ExtendedTempObject.new(datastore.retrieve(uid), self)
151
- temp_object.transform(*args)
152
- end
153
-
154
- def generate(*args)
155
- create_object(processors.generate(*args))
156
- end
157
-
158
- # Return the mime type for a given extension, from the registered list
159
- # By default uses the list provided by Rack (see Rack::Mime::MIME_TYPES)
160
- # If not found there, it falls back to the registered analysers (if temp_object provided).
161
- # If not found there, it falls back to the configured 'fallback_mime_type'
162
- # @param [Symbol, String] format the format (file-extension)
163
- # @param [TempObject] temp_object (optional)
164
- # @return [String] the mime-type
165
- # @see register_mime_type
166
- def mime_type_for(format, temp_object=nil)
167
- registered_mime_types[file_ext_string(format)] || (temp_object.mime_type if temp_object.respond_to?(:mime_type)) || fallback_mime_type
168
- end
169
-
170
- # Store an object, using the configured datastore
171
- # @param [String, File, Tempfile, TempObject] object the object holding the data
172
- # @return [String] the uid assigned to it
173
- def store(object)
174
- datastore.store(create_object(object))
175
- end
176
-
177
- def register_analyser(*args, &block)
178
- analysers.register(*args, &block)
179
- end
180
- configuration_method :register_analyser
181
-
182
- def register_processor(*args, &block)
183
- processors.register(*args, &block)
184
- end
185
- configuration_method :register_processor
186
-
187
- def register_encoder(*args, &block)
188
- encoders.register(*args, &block)
189
- end
190
- configuration_method :register_encoder
45
+ configurable_attr :fallback_mime_type, 'application/octet-stream'
46
+ configurable_attr :url_path_prefix
47
+ configurable_attr :url_host
48
+ configurable_attr :protect_from_dos_attacks, false
49
+ configurable_attr :secret
50
+ configurable_attr :log do Logger.new('/var/tmp/dragonfly.log') end
51
+ configurable_attr :infer_mime_type_from_file_ext, true
52
+
53
+ attr_reader :analyser
54
+ attr_reader :processor
55
+ attr_reader :encoder
56
+ attr_reader :generator
57
+ attr_reader :server
58
+
59
+ configuration_method :analyser
60
+ configuration_method :processor
61
+ configuration_method :encoder
62
+ configuration_method :generator
63
+
64
+ attr_accessor :job_definitions
65
+
66
+ SAVED_CONFIGS = {
67
+ :rmagick => 'RMagick',
68
+ :r_magick => 'RMagick',
69
+ :rails => 'Rails',
70
+ :heroku => 'Heroku'
71
+ }
72
+
73
+ def configurer_for(symbol)
74
+ class_name = SAVED_CONFIGS[symbol]
75
+ if class_name.nil?
76
+ raise ArgumentError, "#{symbol.inspect} is not a known configuration - try one of #{SAVED_CONFIGS.keys.join(', ')}"
77
+ end
78
+ Config.const_get(class_name)
79
+ end
80
+
81
+ def new_job(content=nil, opts={})
82
+ content ? Job.new(self, TempObject.new(content, opts)) : Job.new(self)
83
+ end
84
+
85
+ def endpoint(job=nil, &block)
86
+ block ? RoutedEndpoint.new(self, &block) : JobEndpoint.new(job)
87
+ end
88
+
89
+ def job(name, &block)
90
+ job_definitions.add(name, &block)
91
+ end
92
+ configuration_method :job
93
+
94
+ def store(object, opts={})
95
+ temp_object = object.is_a?(TempObject) ? object : TempObject.new(object)
96
+ temp_object.extract_attributes_from(opts)
97
+ datastore.store(temp_object, opts)
98
+ end
191
99
 
192
100
  def register_mime_type(format, mime_type)
193
101
  registered_mime_types[file_ext_string(format)] = mime_type
@@ -198,15 +106,72 @@ module Dragonfly
198
106
  @registered_mime_types ||= Rack::Mime::MIME_TYPES.dup
199
107
  end
200
108
 
201
- private
109
+ def mime_type_for(format)
110
+ registered_mime_types[file_ext_string(format)]
111
+ end
112
+
113
+ def resolve_mime_type(temp_object)
114
+ mime_type_for(temp_object.format) ||
115
+ (mime_type_for(temp_object.ext) if infer_mime_type_from_file_ext) ||
116
+ analyser.analyse(temp_object, :mime_type) ||
117
+ mime_type_for(analyser.analyse(temp_object, :format)) ||
118
+ fallback_mime_type
119
+ end
120
+
121
+ def mount_path
122
+ url_path_prefix.blank? ? '/' : url_path_prefix
123
+ end
202
124
 
203
- def warn_with_info(message, env)
204
- log.warn "Got error: #{message}\nPath was #{env['PATH_INFO'].inspect} and query was #{env['QUERY_STRING'].inspect}"
125
+ def url_for(job, *args)
126
+ if (args.length == 1 && args.first.kind_of?(Hash)) || args.empty?
127
+ opts = args.first || {}
128
+ host = opts[:host] || url_host
129
+ path_prefix = opts[:path_prefix] || url_path_prefix
130
+ path = "#{host}#{path_prefix}#{job.to_path}"
131
+ path << "?#{dos_protection_query_string(job)}" if protect_from_dos_attacks
132
+ path
133
+ else
134
+ # Deprecation stuff - will be removed!!!
135
+ case args[0]
136
+ when /^(\d+)?x(\d+)?/
137
+ log.warn("DEPRECATED USE OF url_for and will be removed in the future - please use thumb(#{args.map{|a|a.inspect}.join(', ')}).url")
138
+ args[1] ? job.thumb(args[0], args[1]).url : job.thumb(args[0]).url
139
+ when :gif, :png, :jpg, :jpeg
140
+ log.warn("DEPRECATED USE OF url_for and will be removed in the future - please use encode(#{args.first.inspect}).url")
141
+ job.encode(args[0]).url
142
+ else
143
+ raise "DEPRECATED USE OF url_for - will be removed in future versions - please consult the docs"
144
+ end
145
+ end
146
+ end
147
+
148
+ def define_macro(mod, macro_name)
149
+ already_extended = (class << mod; self; end).included_modules.include?(ActiveModelExtensions)
150
+ mod.extend(ActiveModelExtensions) unless already_extended
151
+ mod.register_dragonfly_app(macro_name, self)
152
+ end
153
+
154
+ def define_macro_on_include(mod, macro_name)
155
+ app = self
156
+ (class << mod; self; end).class_eval do
157
+ alias included_without_dragonfly included
158
+ define_method :included_with_dragonfly do |mod|
159
+ included_without_dragonfly(mod)
160
+ app.define_macro(mod, macro_name)
161
+ end
162
+ alias included included_with_dragonfly
163
+ end
205
164
  end
206
-
165
+
166
+ private
167
+
207
168
  def file_ext_string(format)
208
169
  '.' + format.to_s.downcase.sub(/^.*\./,'')
209
170
  end
210
171
 
172
+ def dos_protection_query_string(job)
173
+ server.required_params_for(job).map{|k,v| "#{k}=#{v}" }.join('&')
174
+ end
175
+
211
176
  end
212
177
  end