dragonfly 0.8.6 → 0.9.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 (155) hide show
  1. data/{.specopts → .rspec} +0 -1
  2. data/.yardopts +6 -2
  3. data/Gemfile +14 -13
  4. data/History.md +47 -9
  5. data/README.md +25 -5
  6. data/Rakefile +37 -79
  7. data/VERSION +1 -1
  8. data/dragonfly.gemspec +140 -89
  9. data/extra_docs/Analysers.md +8 -48
  10. data/extra_docs/Configuration.md +40 -25
  11. data/extra_docs/Couch.md +49 -0
  12. data/extra_docs/DataStorage.md +94 -24
  13. data/extra_docs/Encoding.md +6 -35
  14. data/extra_docs/ExampleUseCases.md +113 -0
  15. data/extra_docs/GeneralUsage.md +7 -23
  16. data/extra_docs/Generators.md +15 -49
  17. data/extra_docs/Heroku.md +7 -8
  18. data/extra_docs/ImageMagick.md +126 -0
  19. data/extra_docs/MimeTypes.md +3 -3
  20. data/extra_docs/Models.md +163 -0
  21. data/extra_docs/Mongo.md +1 -4
  22. data/extra_docs/Processing.md +7 -60
  23. data/extra_docs/Rails2.md +3 -1
  24. data/extra_docs/Rails3.md +2 -10
  25. data/extra_docs/ServingRemotely.md +83 -0
  26. data/extra_docs/Sinatra.md +3 -3
  27. data/extra_docs/URLs.md +60 -33
  28. data/features/rails_3.0.5.feature +8 -0
  29. data/features/steps/rails_steps.rb +7 -18
  30. data/features/support/env.rb +10 -37
  31. data/features/support/setup.rb +32 -0
  32. data/fixtures/rails_3.0.5/files/app/models/album.rb +5 -0
  33. data/fixtures/rails_3.0.5/files/app/views/albums/new.html.erb +7 -0
  34. data/fixtures/{files → rails_3.0.5/files}/app/views/albums/show.html.erb +2 -0
  35. data/fixtures/{files → rails_3.0.5/files}/config/initializers/dragonfly.rb +0 -0
  36. data/fixtures/rails_3.0.5/files/features/manage_album_images.feature +38 -0
  37. data/fixtures/rails_3.0.5/files/features/step_definitions/helper_steps.rb +7 -0
  38. data/fixtures/{files → rails_3.0.5/files}/features/step_definitions/image_steps.rb +11 -1
  39. data/fixtures/{files → rails_3.0.5/files}/features/support/paths.rb +2 -0
  40. data/fixtures/{files → rails_3.0.5/files}/features/text_images.feature +0 -0
  41. data/fixtures/{rails_3.0.3 → rails_3.0.5}/template.rb +2 -2
  42. data/irbrc.rb +2 -1
  43. data/lib/dragonfly.rb +7 -0
  44. data/lib/dragonfly/active_model_extensions/attachment.rb +134 -46
  45. data/lib/dragonfly/active_model_extensions/attachment_class_methods.rb +144 -0
  46. data/lib/dragonfly/active_model_extensions/class_methods.rb +62 -9
  47. data/lib/dragonfly/active_model_extensions/instance_methods.rb +2 -2
  48. data/lib/dragonfly/active_model_extensions/validations.rb +10 -6
  49. data/lib/dragonfly/analyser.rb +0 -1
  50. data/lib/dragonfly/analysis/file_command_analyser.rb +1 -1
  51. data/lib/dragonfly/analysis/image_magick_analyser.rb +2 -43
  52. data/lib/dragonfly/app.rb +64 -55
  53. data/lib/dragonfly/config/heroku.rb +1 -1
  54. data/lib/dragonfly/config/image_magick.rb +2 -37
  55. data/lib/dragonfly/config/rails.rb +5 -2
  56. data/lib/dragonfly/configurable.rb +115 -35
  57. data/lib/dragonfly/core_ext/object.rb +1 -1
  58. data/lib/dragonfly/core_ext/string.rb +1 -1
  59. data/lib/dragonfly/data_storage/couch_data_store.rb +84 -0
  60. data/lib/dragonfly/data_storage/file_data_store.rb +43 -18
  61. data/lib/dragonfly/data_storage/mongo_data_store.rb +8 -4
  62. data/lib/dragonfly/data_storage/s3data_store.rb +82 -38
  63. data/lib/dragonfly/encoding/image_magick_encoder.rb +2 -53
  64. data/lib/dragonfly/function_manager.rb +4 -2
  65. data/lib/dragonfly/generation/image_magick_generator.rb +2 -136
  66. data/lib/dragonfly/hash_with_css_style_keys.rb +21 -0
  67. data/lib/dragonfly/image_magick/analyser.rb +51 -0
  68. data/lib/dragonfly/image_magick/config.rb +44 -0
  69. data/lib/dragonfly/{encoding/r_magick_encoder.rb → image_magick/encoder.rb} +10 -14
  70. data/lib/dragonfly/image_magick/generator.rb +145 -0
  71. data/lib/dragonfly/image_magick/processor.rb +104 -0
  72. data/lib/dragonfly/image_magick/utils.rb +72 -0
  73. data/lib/dragonfly/image_magick_utils.rb +2 -79
  74. data/lib/dragonfly/job.rb +152 -90
  75. data/lib/dragonfly/middleware.rb +5 -19
  76. data/lib/dragonfly/processing/image_magick_processor.rb +2 -95
  77. data/lib/dragonfly/rails/images.rb +15 -10
  78. data/lib/dragonfly/response.rb +26 -12
  79. data/lib/dragonfly/serializer.rb +1 -4
  80. data/lib/dragonfly/server.rb +103 -0
  81. data/lib/dragonfly/temp_object.rb +56 -101
  82. data/lib/dragonfly/url_mapper.rb +78 -0
  83. data/spec/dragonfly/active_model_extensions/model_spec.rb +772 -65
  84. data/spec/dragonfly/active_model_extensions/spec_helper.rb +90 -10
  85. data/spec/dragonfly/analyser_spec.rb +1 -1
  86. data/spec/dragonfly/analysis/file_command_analyser_spec.rb +5 -14
  87. data/spec/dragonfly/app_spec.rb +35 -180
  88. data/spec/dragonfly/configurable_spec.rb +259 -18
  89. data/spec/dragonfly/core_ext/string_spec.rb +2 -2
  90. data/spec/dragonfly/core_ext/symbol_spec.rb +1 -1
  91. data/spec/dragonfly/data_storage/couch_data_store_spec.rb +84 -0
  92. data/spec/dragonfly/data_storage/file_data_store_spec.rb +149 -22
  93. data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +21 -2
  94. data/spec/dragonfly/data_storage/s3_data_store_spec.rb +207 -43
  95. data/spec/dragonfly/data_storage/{data_store_spec.rb → shared_data_store_examples.rb} +16 -15
  96. data/spec/dragonfly/function_manager_spec.rb +2 -2
  97. data/spec/dragonfly/{generation/hash_with_css_style_keys_spec.rb → hash_with_css_style_keys_spec.rb} +2 -2
  98. data/spec/dragonfly/{analysis/shared_analyser_spec.rb → image_magick/analyser_spec.rb} +19 -6
  99. data/spec/dragonfly/{encoding/image_magick_encoder_spec.rb → image_magick/encoder_spec.rb} +2 -2
  100. data/spec/dragonfly/image_magick/generator_spec.rb +172 -0
  101. data/spec/dragonfly/{processing/shared_processing_spec.rb → image_magick/processor_spec.rb} +55 -6
  102. data/spec/dragonfly/image_magick/utils_spec.rb +18 -0
  103. data/spec/dragonfly/job_builder_spec.rb +1 -1
  104. data/spec/dragonfly/job_definitions_spec.rb +1 -1
  105. data/spec/dragonfly/job_endpoint_spec.rb +26 -3
  106. data/spec/dragonfly/job_spec.rb +426 -208
  107. data/spec/dragonfly/loggable_spec.rb +2 -2
  108. data/spec/dragonfly/middleware_spec.rb +5 -26
  109. data/spec/dragonfly/routed_endpoint_spec.rb +1 -1
  110. data/spec/dragonfly/serializer_spec.rb +1 -14
  111. data/spec/dragonfly/server_spec.rb +261 -0
  112. data/spec/dragonfly/simple_cache_spec.rb +1 -1
  113. data/spec/dragonfly/temp_object_spec.rb +84 -130
  114. data/spec/dragonfly/url_mapper_spec.rb +130 -0
  115. data/spec/functional/deprecations_spec.rb +51 -0
  116. data/spec/functional/image_magick_app_spec.rb +27 -0
  117. data/spec/functional/model_urls_spec.rb +85 -0
  118. data/spec/functional/remote_on_the_fly_spec.rb +51 -0
  119. data/spec/functional/to_response_spec.rb +31 -0
  120. data/spec/spec_helper.rb +12 -22
  121. data/spec/{argument_matchers.rb → support/argument_matchers.rb} +0 -0
  122. data/spec/{image_matchers.rb → support/image_matchers.rb} +4 -4
  123. data/spec/support/simple_matchers.rb +53 -0
  124. data/yard/handlers/configurable_attr_handler.rb +2 -2
  125. data/yard/templates/default/fulldoc/html/css/common.css +12 -10
  126. data/yard/templates/default/layout/html/layout.erb +6 -0
  127. metadata +267 -308
  128. data/Gemfile.rails.2.3.5 +0 -20
  129. data/features/3.0.3.feature +0 -8
  130. data/features/rails_2.3.5.feature +0 -7
  131. data/fixtures/files/app/models/album.rb +0 -3
  132. data/fixtures/files/app/views/albums/new.html.erb +0 -4
  133. data/fixtures/files/features/manage_album_images.feature +0 -12
  134. data/fixtures/rails_2.3.5/template.rb +0 -10
  135. data/lib/dragonfly/analysis/r_magick_analyser.rb +0 -63
  136. data/lib/dragonfly/config/r_magick.rb +0 -46
  137. data/lib/dragonfly/generation/hash_with_css_style_keys.rb +0 -23
  138. data/lib/dragonfly/generation/r_magick_generator.rb +0 -155
  139. data/lib/dragonfly/processing/r_magick_processor.rb +0 -126
  140. data/lib/dragonfly/r_magick_utils.rb +0 -48
  141. data/lib/dragonfly/simple_endpoint.rb +0 -76
  142. data/spec/dragonfly/active_model_extensions/active_model_setup.rb +0 -97
  143. data/spec/dragonfly/active_model_extensions/active_record_setup.rb +0 -85
  144. data/spec/dragonfly/analysis/image_magick_analyser_spec.rb +0 -15
  145. data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +0 -31
  146. data/spec/dragonfly/config/r_magick_spec.rb +0 -29
  147. data/spec/dragonfly/encoding/r_magick_encoder_spec.rb +0 -41
  148. data/spec/dragonfly/generation/image_magick_generator_spec.rb +0 -12
  149. data/spec/dragonfly/generation/r_magick_generator_spec.rb +0 -28
  150. data/spec/dragonfly/generation/shared_generator_spec.rb +0 -91
  151. data/spec/dragonfly/image_magick_utils_spec.rb +0 -16
  152. data/spec/dragonfly/processing/image_magick_processor_spec.rb +0 -29
  153. data/spec/dragonfly/processing/r_magick_processor_spec.rb +0 -30
  154. data/spec/dragonfly/simple_endpoint_spec.rb +0 -97
  155. data/spec/simple_matchers.rb +0 -44
@@ -0,0 +1,144 @@
1
+ module Dragonfly
2
+ module ActiveModelExtensions
3
+ class Attachment
4
+ class << self
5
+
6
+ class ConfigProxy
7
+
8
+ def initialize(spec, block)
9
+ @spec = spec
10
+ instance_eval(&block)
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :spec
16
+
17
+ def after_assign(*callbacks, &block)
18
+ add_callbacks(:after_assign, *callbacks, &block)
19
+ end
20
+
21
+ def after_unassign(*callbacks, &block)
22
+ add_callbacks(:after_unassign, *callbacks, &block)
23
+ end
24
+
25
+ def copy_to(accessor, &block)
26
+ after_assign do |a|
27
+ self.send "#{accessor}=", (block_given? ? instance_exec(a, &block) : a)
28
+ end
29
+ after_unassign{|a| self.send("#{accessor}=", nil) }
30
+ end
31
+
32
+ def storage_opts(opts=nil, &block)
33
+ spec.storage_opts_specs << (opts || block)
34
+ end
35
+
36
+ def storage_opt(key, value, &block)
37
+ if value.is_a? Symbol
38
+ storage_opts{|a| {key => send(value)} }
39
+ elsif block_given?
40
+ storage_opts{|a| {key => instance_exec(a, &block)} }
41
+ else
42
+ storage_opts{|a| {key => value} }
43
+ end
44
+ end
45
+
46
+ def add_callbacks(name, *callbacks, &block)
47
+ if block_given?
48
+ spec.callbacks[name] << block
49
+ else
50
+ spec.callbacks[name].push(*callbacks)
51
+ end
52
+ end
53
+
54
+ def method_missing(meth, *args, &block)
55
+ if meth.to_s =~ /^storage_(.*)$/
56
+ storage_opt($1.to_sym, args.first, &block)
57
+ else
58
+ super
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ def init(model_class, attribute, app, config_block)
65
+ @model_class, @attribute, @app, @config_block = model_class, attribute, app, config_block
66
+ include app.analyser.analysis_methods
67
+ include app.job_definitions
68
+ define_method :format do
69
+ job.format
70
+ end
71
+ define_method :mime_type do
72
+ job.mime_type
73
+ end
74
+ ConfigProxy.new(self, config_block) if config_block
75
+ self
76
+ end
77
+
78
+ attr_reader :model_class, :attribute, :app, :config_block
79
+
80
+ # Callbacks
81
+ def callbacks
82
+ @callbacks ||= Hash.new{|h,k| h[k] = [] }
83
+ end
84
+
85
+ def run_callbacks(name, model, attachment)
86
+ attachment.should_run_callbacks = false
87
+ callbacks[name].each do |callback|
88
+ case callback
89
+ when Symbol then model.send(callback)
90
+ when Proc then model.instance_exec(attachment, &callback)
91
+ end
92
+ end
93
+ attachment.should_run_callbacks = true
94
+ end
95
+
96
+ # Magic attributes
97
+ def allowed_magic_attributes
98
+ app.analyser.analysis_method_names + [:size, :basename, :name, :ext, :meta]
99
+ end
100
+
101
+ def magic_attributes
102
+ @magic_attributes ||= begin
103
+ prefix = attribute.to_s + '_'
104
+ model_class.public_instance_methods.inject([]) do |attrs, name|
105
+ _, __, suffix = name.to_s.partition(prefix)
106
+ if !suffix.empty? && allowed_magic_attributes.include?(suffix.to_sym)
107
+ attrs << suffix.to_sym
108
+ end
109
+ attrs
110
+ end
111
+ end
112
+ end
113
+
114
+ def ensure_uses_cached_magic_attributes
115
+ return if @uses_cached_magic_attributes
116
+ magic_attributes.each do |attr|
117
+ define_method attr do
118
+ magic_attribute_for(attr)
119
+ end
120
+ end
121
+ @uses_cached_magic_attributes = true
122
+ end
123
+
124
+ # Storage options
125
+ def storage_opts_specs
126
+ @storage_opts_specs ||= []
127
+ end
128
+
129
+ def evaluate_storage_opts(model, attachment)
130
+ storage_opts_specs.inject({}) do |opts, spec|
131
+ options = case spec
132
+ when Proc then model.instance_exec(attachment, &spec)
133
+ when Symbol then model.send(spec)
134
+ else spec
135
+ end
136
+ opts.merge!(options)
137
+ opts
138
+ end
139
+ end
140
+
141
+ end
142
+ end
143
+ end
144
+ end
@@ -7,15 +7,15 @@ module Dragonfly
7
7
  def register_dragonfly_app(macro_name, app)
8
8
  (class << self; self; end).class_eval do
9
9
 
10
- # Defines e.g. 'image_accessor' for any activerecord class body
11
- define_method macro_name do |attribute|
10
+ # Defines e.g. 'image_accessor' for any activemodel class body
11
+ define_method macro_name do |attribute, &config_block|
12
12
 
13
- # Prior to activerecord 3, adding before callbacks more than once does add it more than once
14
- before_save :save_dragonfly_attachments unless respond_to?(:before_save_callback_chain) && before_save_callback_chain.find(:save_dragonfly_attachments)
15
- before_destroy :destroy_dragonfly_attachments unless respond_to?(:before_destroy_callback_chain) && before_destroy_callback_chain.find(:destroy_dragonfly_attachments)
13
+ # Add callbacks
14
+ before_save :save_dragonfly_attachments
15
+ before_destroy :destroy_dragonfly_attachments
16
16
 
17
17
  # Register the new attribute
18
- dragonfly_apps_for_attributes[attribute] = app
18
+ dragonfly_attachment_classes << new_dragonfly_attachment_class(attribute, app, config_block)
19
19
 
20
20
  # Define the setter for the attribute
21
21
  define_method "#{attribute}=" do |value|
@@ -27,19 +27,72 @@ module Dragonfly
27
27
  dragonfly_attachments[attribute].to_value
28
28
  end
29
29
 
30
+ # Define the URL setter
31
+ define_method "#{attribute}_url=" do |url|
32
+ unless url.blank?
33
+ dragonfly_attachments[attribute].assign(app.fetch_url(url))
34
+ end
35
+ end
36
+
37
+ # Define the URL getter
38
+ define_method "#{attribute}_url" do
39
+ nil
40
+ end
41
+
42
+ # Define the remove setter
43
+ define_method "remove_#{attribute}=" do |value|
44
+ unless [0, "0", false, "false", "", nil].include?(value)
45
+ dragonfly_attachments[attribute].assign(nil)
46
+ instance_variable_set("@remove_#{attribute}", true)
47
+ end
48
+ end
49
+
50
+ # Define the remove getter
51
+ attr_reader "remove_#{attribute}"
52
+
53
+ # Define the retained setter
54
+ define_method "retained_#{attribute}=" do |string|
55
+ unless string.blank?
56
+ begin
57
+ dragonfly_attachments[attribute].retained_attrs = Serializer.marshal_decode(string)
58
+ rescue Serializer::BadString => e
59
+ app.log.warn("*** WARNING ***: couldn't update attachment with serialized retained_#{attribute} string #{string.inspect}")
60
+ end
61
+ end
62
+ dragonfly_attachments[attribute].should_retain = true
63
+ dragonfly_attachments[attribute].retain!
64
+ string
65
+ end
66
+
67
+ # Define the retained getter
68
+ define_method "retained_#{attribute}" do
69
+ attrs = dragonfly_attachments[attribute].retained_attrs
70
+ Serializer.marshal_encode(attrs) if attrs
71
+ end
72
+
30
73
  end
31
74
 
32
75
  end
33
76
  app
34
77
  end
35
78
 
36
- def dragonfly_apps_for_attributes
37
- @dragonfly_apps_for_attributes ||= begin
79
+ def dragonfly_attachment_classes
80
+ @dragonfly_attachment_classes ||= begin
38
81
  parent_class = ancestors.select{|a| a.is_a?(Class) }[1]
39
- parent_class.respond_to?(:dragonfly_apps_for_attributes) ? parent_class.dragonfly_apps_for_attributes.dup : {}
82
+ if parent_class.respond_to?(:dragonfly_attachment_classes)
83
+ parent_class.dragonfly_attachment_classes.map do |klass|
84
+ new_dragonfly_attachment_class(klass.attribute, klass.app, klass.config_block)
85
+ end
86
+ else
87
+ []
88
+ end
40
89
  end
41
90
  end
42
91
 
92
+ def new_dragonfly_attachment_class(attribute, app, config_block)
93
+ Class.new(Attachment).init(self, attribute, app, config_block)
94
+ end
95
+
43
96
  end
44
97
  end
45
98
  end
@@ -3,8 +3,8 @@ module Dragonfly
3
3
  module InstanceMethods
4
4
 
5
5
  def dragonfly_attachments
6
- @dragonfly_attachments ||= self.class.dragonfly_apps_for_attributes.inject({}) do |hash, (attribute, app)|
7
- hash[attribute] = Attachment.new(app, self, attribute)
6
+ @dragonfly_attachments ||= self.class.dragonfly_attachment_classes.inject({}) do |hash, klass|
7
+ hash[klass.attribute] = klass.new(self)
8
8
  hash
9
9
  end
10
10
  end
@@ -12,19 +12,23 @@ module Dragonfly
12
12
  allowed_values = opts[:in] || [opts[:as]]
13
13
 
14
14
  args = attrs + [opts]
15
- validates_each(*args) do |record, attr, attachment|
15
+ validates_each(*args) do |model, attr, attachment|
16
16
  if attachment
17
17
  property = attachment.send(property_name)
18
- record.errors.add(attr,
19
- opts[:message] ||
20
- "#{property_name.to_s.humanize.downcase} is incorrect. It needs to be #{expected_values_string(allowed_values)}, but was '#{property}'"
21
- ) unless allowed_values.include?(property)
18
+ unless allowed_values.include?(property)
19
+ message = opts[:message] ||
20
+ "#{property_name.to_s.humanize.downcase} is incorrect. "+
21
+ "It needs to be #{Validations.expected_values_string(allowed_values)}"+
22
+ (property ? ", but was '#{property}'" : "")
23
+ message = message.call(property, model) if message.respond_to?(:call)
24
+ model.errors.add(attr, message)
25
+ end
22
26
  end
23
27
  end
24
28
 
25
29
  end
26
30
 
27
- def expected_values_string(allowed_values)
31
+ def self.expected_values_string(allowed_values)
28
32
  if allowed_values.is_a?(Range)
29
33
  "between #{allowed_values.first} and #{allowed_values.last}"
30
34
  else
@@ -1,7 +1,6 @@
1
1
  module Dragonfly
2
2
  class Analyser < FunctionManager
3
3
 
4
- include Configurable
5
4
  configurable_attr :enable_cache, true
6
5
  configurable_attr :cache_size, 100
7
6
 
@@ -6,7 +6,7 @@ module Dragonfly
6
6
  include Configurable
7
7
 
8
8
  configurable_attr :file_command, "file"
9
- configurable_attr :use_filesystem, false
9
+ configurable_attr :use_filesystem, true
10
10
  configurable_attr :num_bytes_to_check, 255
11
11
 
12
12
  def mime_type(temp_object)
@@ -1,47 +1,6 @@
1
1
  module Dragonfly
2
2
  module Analysis
3
- class ImageMagickAnalyser
4
-
5
- include ImageMagickUtils
6
- include Configurable
7
-
8
- def width(temp_object)
9
- identify(temp_object)[:width]
10
- end
11
-
12
- def height(temp_object)
13
- identify(temp_object)[:height]
14
- end
15
-
16
- def aspect_ratio(temp_object)
17
- attrs = identify(temp_object)
18
- attrs[:width].to_f / attrs[:height]
19
- end
20
-
21
- def portrait?(temp_object)
22
- attrs = identify(temp_object)
23
- attrs[:width] <= attrs[:height]
24
- end
25
-
26
- def landscape?(temp_object)
27
- attrs = identify(temp_object)
28
- attrs[:width] >= attrs[:height]
29
- end
30
-
31
- def depth(temp_object)
32
- identify(temp_object)[:depth]
33
- end
34
-
35
- def number_of_colours(temp_object)
36
- details = raw_identify(temp_object, '-verbose -unique')
37
- details[/Colors: (\d+)/, 1].to_i
38
- end
39
- alias number_of_colors number_of_colours
40
-
41
- def format(temp_object)
42
- identify(temp_object)[:format]
43
- end
44
-
45
- end
3
+ puts "WARNING: Dragonfly::Analysis::ImageMagickAnalyser is DEPRECATED and will soon be removed. Please use Dragonfly::ImageMagick::Analyser instead."
4
+ ImageMagickAnalyser = ImageMagick::Analyser
46
5
  end
47
6
  end
@@ -25,33 +25,29 @@ module Dragonfly
25
25
 
26
26
  def initialize
27
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)
28
+ [@analyser, @processor, @encoder, @generator].each do |obj|
29
+ obj.use_same_log_as(self)
30
+ obj.use_as_fallback_config(self)
31
+ end
32
+ @server = Server.new(self)
32
33
  @job_definitions = JobDefinitions.new
33
- @server = Dragonfly::SimpleEndpoint.new(self)
34
34
  end
35
35
 
36
36
  include Configurable
37
37
 
38
38
  extend Forwardable
39
39
  def_delegator :datastore, :destroy
40
- def_delegators :new_job, :fetch, :generate, :fetch_file
41
- def_delegator :server, :call
40
+ def_delegators :new_job, :fetch, :generate, :fetch_file, :fetch_url
41
+ def_delegators :server, :call
42
42
 
43
43
  configurable_attr :datastore do DataStorage::FileDataStore.new end
44
44
  configurable_attr :cache_duration, 3600*24*365 # (1 year)
45
45
  configurable_attr :fallback_mime_type, 'application/octet-stream'
46
- configurable_attr :url_path_prefix
47
- configurable_attr :url_host
48
- configurable_attr :url_suffix
49
- configurable_attr :protect_from_dos_attacks, false
50
46
  configurable_attr :secret, 'secret yo'
51
47
  configurable_attr :log do Logger.new('/var/tmp/dragonfly.log') end
52
- configurable_attr :infer_mime_type_from_file_ext, true
48
+ configurable_attr :trust_file_extensions, true
53
49
  configurable_attr :content_disposition
54
- configurable_attr :content_filename, Response::DEFAULT_FILENAME
50
+ configurable_attr :content_filename, Dragonfly::Response::DEFAULT_FILENAME
55
51
 
56
52
  attr_reader :analyser
57
53
  attr_reader :processor
@@ -59,33 +55,14 @@ module Dragonfly
59
55
  attr_reader :generator
60
56
  attr_reader :server
61
57
 
62
- configuration_method :analyser
63
- configuration_method :processor
64
- configuration_method :encoder
65
- configuration_method :generator
58
+ nested_configurable :server, :analyser, :processor, :encoder, :generator
66
59
 
67
60
  attr_accessor :job_definitions
68
61
 
69
- SAVED_CONFIGS = {
70
- :imagemagick => 'ImageMagick',
71
- :image_magick => 'ImageMagick',
72
- :rmagick => 'RMagick',
73
- :r_magick => 'RMagick',
74
- :rails => 'Rails',
75
- :heroku => 'Heroku'
76
- }
77
-
78
- def configurer_for(symbol)
79
- class_name = SAVED_CONFIGS[symbol]
80
- if class_name.nil?
81
- raise ArgumentError, "#{symbol.inspect} is not a known configuration - try one of #{SAVED_CONFIGS.keys.join(', ')}"
82
- end
83
- Config.const_get(class_name)
84
- end
85
-
86
- def new_job(content=nil, opts={})
87
- content ? Job.new(self, TempObject.new(content, opts)) : Job.new(self)
62
+ def new_job(content=nil, meta={})
63
+ job_class.new(self, content, meta)
88
64
  end
65
+ alias create new_job
89
66
 
90
67
  def endpoint(job=nil, &block)
91
68
  block ? RoutedEndpoint.new(self, &block) : JobEndpoint.new(job)
@@ -96,9 +73,20 @@ module Dragonfly
96
73
  end
97
74
  configuration_method :job
98
75
 
76
+ def job_class
77
+ @job_class ||= begin
78
+ app = self
79
+ Class.new(Job).class_eval do
80
+ include app.analyser.analysis_methods
81
+ include app.job_definitions
82
+ include Job::OverrideInstanceMethods
83
+ self
84
+ end
85
+ end
86
+ end
87
+
99
88
  def store(object, opts={})
100
89
  temp_object = object.is_a?(TempObject) ? object : TempObject.new(object)
101
- temp_object.extract_attributes_from(opts)
102
90
  datastore.store(temp_object, opts)
103
91
  end
104
92
 
@@ -115,29 +103,28 @@ module Dragonfly
115
103
  registered_mime_types[file_ext_string(format)]
116
104
  end
117
105
 
118
- def resolve_mime_type(temp_object)
119
- mime_type_for(temp_object.format) ||
120
- (mime_type_for(temp_object.ext) if infer_mime_type_from_file_ext) ||
121
- analyser.analyse(temp_object, :mime_type) ||
122
- mime_type_for(analyser.analyse(temp_object, :format)) ||
123
- fallback_mime_type
106
+ def response_headers
107
+ @response_headers ||= {}
124
108
  end
109
+ configuration_method :response_headers
125
110
 
126
- def mount_path
127
- url_path_prefix.blank? ? '/' : url_path_prefix
111
+ def define_url(&block)
112
+ @url_proc = block
128
113
  end
114
+ configuration_method :define_url
129
115
 
130
116
  def url_for(job, opts={})
131
- opts = opts.dup
132
- host = opts.delete(:host) || url_host
133
- suffix = opts.delete(:suffix) || url_suffix
134
- suffix = suffix.call(job) if suffix.respond_to?(:call)
135
- path_prefix = opts.delete(:path_prefix) || url_path_prefix
136
- path = "#{host}#{path_prefix}#{job.to_path}#{suffix}"
137
- query = opts
138
- query.merge!(server.required_params_for(job)) if protect_from_dos_attacks
139
- path << "?#{Rack::Utils.build_query(query)}" if query.any?
140
- path
117
+ if @url_proc
118
+ @url_proc.call(self, job, opts)
119
+ else
120
+ server.url_for(job, opts)
121
+ end
122
+ end
123
+
124
+ def remote_url_for(uid, opts={})
125
+ datastore.url_for(uid, opts)
126
+ rescue NoMethodError => e
127
+ raise NotImplementedError, "The datastore doesn't support serving content directly - #{datastore.inspect}"
141
128
  end
142
129
 
143
130
  def define_macro(mod, macro_name)
@@ -157,9 +144,31 @@ module Dragonfly
157
144
  alias included included_with_dragonfly
158
145
  end
159
146
  end
147
+
148
+ # Deprecated methods
149
+ def url_path_prefix=(thing)
150
+ raise NoMethodError, "url_path_prefix is deprecated - please use url_format, e.g. url_format = '/media/:job/:basename.:format' - see docs for more details"
151
+ end
152
+ configuration_method :url_path_prefix=
153
+
154
+ def url_suffix=(thing)
155
+ raise NoMethodError, "url_suffix is deprecated - please use url_format, e.g. url_format = '/media/:job/:basename.:format' - see docs for more details"
156
+ end
157
+ configuration_method :url_suffix=
158
+
159
+ def infer_mime_type_from_file_ext=(bool)
160
+ raise NoMethodError, "infer_mime_type_from_file_ext is deprecated - please use trust_file_extensions = #{bool.inspect} instead"
161
+ end
162
+ configuration_method :infer_mime_type_from_file_ext=
160
163
 
161
164
  private
162
165
 
166
+ attr_accessor :get_remote_url
167
+
168
+ def saved_configs
169
+ self.class.saved_configs
170
+ end
171
+
163
172
  def file_ext_string(format)
164
173
  '.' + format.to_s.downcase.sub(/^.*\./,'')
165
174
  end