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.
- data/.specopts +2 -0
- data/.yardopts +23 -0
- data/Gemfile +23 -0
- data/Gemfile.rails.2.3.5 +14 -0
- data/History.md +266 -0
- data/LICENSE +20 -0
- data/README.md +88 -0
- data/Rakefile +92 -0
- data/VERSION +1 -0
- data/config.ru +13 -0
- data/docs.watchr +1 -0
- data/dragonfly.gemspec +293 -0
- data/extra_docs/Analysers.md +108 -0
- data/extra_docs/Caching.md +23 -0
- data/extra_docs/Configuration.md +138 -0
- data/extra_docs/DataStorage.md +136 -0
- data/extra_docs/Encoding.md +96 -0
- data/extra_docs/GeneralUsage.md +121 -0
- data/extra_docs/Generators.md +102 -0
- data/extra_docs/Heroku.md +50 -0
- data/extra_docs/Index.md +36 -0
- data/extra_docs/MimeTypes.md +40 -0
- data/extra_docs/Models.md +266 -0
- data/extra_docs/Mongo.md +45 -0
- data/extra_docs/Processing.md +130 -0
- data/extra_docs/Rack.md +52 -0
- data/extra_docs/Rails2.md +55 -0
- data/extra_docs/Rails3.md +62 -0
- data/extra_docs/Sinatra.md +25 -0
- data/extra_docs/URLs.md +169 -0
- data/features/3.0.3.feature +8 -0
- data/features/images.feature +47 -0
- data/features/no_processing.feature +14 -0
- data/features/rails_2.3.5.feature +7 -0
- data/features/steps/common_steps.rb +8 -0
- data/features/steps/dragonfly_steps.rb +66 -0
- data/features/steps/rails_steps.rb +39 -0
- data/features/support/env.rb +40 -0
- data/fixtures/files/app/models/album.rb +3 -0
- data/fixtures/files/app/views/albums/new.html.erb +4 -0
- data/fixtures/files/app/views/albums/show.html.erb +4 -0
- data/fixtures/files/config/initializers/dragonfly.rb +4 -0
- data/fixtures/files/features/manage_album_images.feature +12 -0
- data/fixtures/files/features/step_definitions/image_steps.rb +15 -0
- data/fixtures/files/features/support/paths.rb +15 -0
- data/fixtures/files/features/text_images.feature +7 -0
- data/fixtures/rails_2.3.5/template.rb +10 -0
- data/fixtures/rails_3.0.3/template.rb +20 -0
- data/irbrc.rb +17 -0
- data/lib/dragonfly.rb +45 -0
- data/lib/dragonfly/active_model_extensions.rb +13 -0
- data/lib/dragonfly/active_model_extensions/attachment.rb +169 -0
- data/lib/dragonfly/active_model_extensions/class_methods.rb +45 -0
- data/lib/dragonfly/active_model_extensions/instance_methods.rb +28 -0
- data/lib/dragonfly/active_model_extensions/validations.rb +37 -0
- data/lib/dragonfly/analyser.rb +59 -0
- data/lib/dragonfly/analysis/file_command_analyser.rb +32 -0
- data/lib/dragonfly/analysis/image_magick_analyser.rb +47 -0
- data/lib/dragonfly/analysis/r_magick_analyser.rb +63 -0
- data/lib/dragonfly/app.rb +182 -0
- data/lib/dragonfly/config/heroku.rb +19 -0
- data/lib/dragonfly/config/image_magick.rb +41 -0
- data/lib/dragonfly/config/r_magick.rb +46 -0
- data/lib/dragonfly/config/rails.rb +17 -0
- data/lib/dragonfly/configurable.rb +119 -0
- data/lib/dragonfly/core_ext/object.rb +8 -0
- data/lib/dragonfly/core_ext/string.rb +9 -0
- data/lib/dragonfly/core_ext/symbol.rb +9 -0
- data/lib/dragonfly/data_storage.rb +9 -0
- data/lib/dragonfly/data_storage/file_data_store.rb +114 -0
- data/lib/dragonfly/data_storage/mongo_data_store.rb +82 -0
- data/lib/dragonfly/data_storage/s3data_store.rb +115 -0
- data/lib/dragonfly/encoder.rb +13 -0
- data/lib/dragonfly/encoding/image_magick_encoder.rb +57 -0
- data/lib/dragonfly/encoding/r_magick_encoder.rb +61 -0
- data/lib/dragonfly/function_manager.rb +69 -0
- data/lib/dragonfly/generation/hash_with_css_style_keys.rb +23 -0
- data/lib/dragonfly/generation/image_magick_generator.rb +140 -0
- data/lib/dragonfly/generation/r_magick_generator.rb +155 -0
- data/lib/dragonfly/generator.rb +9 -0
- data/lib/dragonfly/image_magick_utils.rb +81 -0
- data/lib/dragonfly/job.rb +371 -0
- data/lib/dragonfly/job_builder.rb +39 -0
- data/lib/dragonfly/job_definitions.rb +26 -0
- data/lib/dragonfly/job_endpoint.rb +15 -0
- data/lib/dragonfly/loggable.rb +28 -0
- data/lib/dragonfly/middleware.rb +34 -0
- data/lib/dragonfly/processing/image_magick_processor.rb +99 -0
- data/lib/dragonfly/processing/r_magick_processor.rb +126 -0
- data/lib/dragonfly/processor.rb +9 -0
- data/lib/dragonfly/r_magick_utils.rb +48 -0
- data/lib/dragonfly/rails/images.rb +22 -0
- data/lib/dragonfly/response.rb +82 -0
- data/lib/dragonfly/routed_endpoint.rb +40 -0
- data/lib/dragonfly/serializer.rb +32 -0
- data/lib/dragonfly/simple_cache.rb +23 -0
- data/lib/dragonfly/simple_endpoint.rb +63 -0
- data/lib/dragonfly/temp_object.rb +220 -0
- data/samples/beach.png +0 -0
- data/samples/egg.png +0 -0
- data/samples/round.gif +0 -0
- data/samples/sample.docx +0 -0
- data/samples/taj.jpg +0 -0
- data/spec/argument_matchers.rb +19 -0
- data/spec/dragonfly/active_model_extensions/active_model_setup.rb +97 -0
- data/spec/dragonfly/active_model_extensions/active_record_setup.rb +85 -0
- data/spec/dragonfly/active_model_extensions/model_spec.rb +723 -0
- data/spec/dragonfly/active_model_extensions/spec_helper.rb +11 -0
- data/spec/dragonfly/analyser_spec.rb +123 -0
- data/spec/dragonfly/analysis/file_command_analyser_spec.rb +57 -0
- data/spec/dragonfly/analysis/image_magick_analyser_spec.rb +15 -0
- data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +27 -0
- data/spec/dragonfly/analysis/shared_analyser_spec.rb +51 -0
- data/spec/dragonfly/app_spec.rb +280 -0
- data/spec/dragonfly/config/r_magick_spec.rb +25 -0
- data/spec/dragonfly/configurable_spec.rb +220 -0
- data/spec/dragonfly/core_ext/string_spec.rb +17 -0
- data/spec/dragonfly/core_ext/symbol_spec.rb +17 -0
- data/spec/dragonfly/data_storage/data_store_spec.rb +76 -0
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +169 -0
- data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +38 -0
- data/spec/dragonfly/data_storage/s3_data_store_spec.rb +94 -0
- data/spec/dragonfly/deprecation_spec.rb +20 -0
- data/spec/dragonfly/encoding/image_magick_encoder_spec.rb +41 -0
- data/spec/dragonfly/encoding/r_magick_encoder_spec.rb +37 -0
- data/spec/dragonfly/function_manager_spec.rb +154 -0
- data/spec/dragonfly/generation/hash_with_css_style_keys_spec.rb +24 -0
- data/spec/dragonfly/generation/image_magick_generator_spec.rb +12 -0
- data/spec/dragonfly/generation/r_magick_generator_spec.rb +24 -0
- data/spec/dragonfly/generation/shared_generator_spec.rb +91 -0
- data/spec/dragonfly/image_magick_utils_spec.rb +16 -0
- data/spec/dragonfly/job_builder_spec.rb +37 -0
- data/spec/dragonfly/job_definitions_spec.rb +35 -0
- data/spec/dragonfly/job_endpoint_spec.rb +120 -0
- data/spec/dragonfly/job_spec.rb +773 -0
- data/spec/dragonfly/loggable_spec.rb +80 -0
- data/spec/dragonfly/middleware_spec.rb +68 -0
- data/spec/dragonfly/processing/image_magick_processor_spec.rb +29 -0
- data/spec/dragonfly/processing/r_magick_processor_spec.rb +26 -0
- data/spec/dragonfly/processing/shared_processing_spec.rb +215 -0
- data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
- data/spec/dragonfly/serializer_spec.rb +61 -0
- data/spec/dragonfly/simple_cache_spec.rb +27 -0
- data/spec/dragonfly/simple_endpoint_spec.rb +89 -0
- data/spec/dragonfly/temp_object_spec.rb +352 -0
- data/spec/image_matchers.rb +47 -0
- data/spec/simple_matchers.rb +44 -0
- data/spec/spec_helper.rb +58 -0
- data/yard/handlers/configurable_attr_handler.rb +38 -0
- data/yard/setup.rb +15 -0
- data/yard/templates/default/fulldoc/html/css/common.css +107 -0
- data/yard/templates/default/layout/html/layout.erb +87 -0
- data/yard/templates/default/module/html/configuration_summary.erb +31 -0
- data/yard/templates/default/module/setup.rb +17 -0
- metadata +550 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Dragonfly
|
|
2
|
+
module ActiveModelExtensions
|
|
3
|
+
module ClassMethods
|
|
4
|
+
|
|
5
|
+
include Validations
|
|
6
|
+
|
|
7
|
+
def register_dragonfly_app(macro_name, app)
|
|
8
|
+
(class << self; self; end).class_eval do
|
|
9
|
+
|
|
10
|
+
# Defines e.g. 'image_accessor' for any activerecord class body
|
|
11
|
+
define_method macro_name do |attribute|
|
|
12
|
+
|
|
13
|
+
# Prior to activerecord 3, adding before callbacks more than once does add it more than once
|
|
14
|
+
before_save :save_attachments unless respond_to?(:before_save_callback_chain) && before_save_callback_chain.find(:save_attachments)
|
|
15
|
+
before_destroy :destroy_attachments unless respond_to?(:before_destroy_callback_chain) && before_destroy_callback_chain.find(:destroy_attachments)
|
|
16
|
+
|
|
17
|
+
# Register the new attribute
|
|
18
|
+
dragonfly_apps_for_attributes[attribute] = app
|
|
19
|
+
|
|
20
|
+
# Define the setter for the attribute
|
|
21
|
+
define_method "#{attribute}=" do |value|
|
|
22
|
+
attachments[attribute].assign(value)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Define the getter for the attribute
|
|
26
|
+
define_method attribute do
|
|
27
|
+
attachments[attribute].to_value
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
app
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def dragonfly_apps_for_attributes
|
|
37
|
+
@dragonfly_apps_for_attributes ||= begin
|
|
38
|
+
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 : {}
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Dragonfly
|
|
2
|
+
module ActiveModelExtensions
|
|
3
|
+
module InstanceMethods
|
|
4
|
+
|
|
5
|
+
def attachments
|
|
6
|
+
@attachments ||= self.class.dragonfly_apps_for_attributes.inject({}) do |hash, (attribute, app)|
|
|
7
|
+
hash[attribute] = Attachment.new(app, self, attribute)
|
|
8
|
+
hash
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def save_attachments
|
|
15
|
+
attachments.each do |attribute, attachment|
|
|
16
|
+
attachment.save!
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def destroy_attachments
|
|
21
|
+
attachments.each do |attribute, attachment|
|
|
22
|
+
attachment.destroy!
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Dragonfly
|
|
2
|
+
module ActiveModelExtensions
|
|
3
|
+
module Validations
|
|
4
|
+
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
def validates_property(property_name, opts)
|
|
8
|
+
attrs = opts[:of] or raise ArgumentError, "you need to provide the attribute which has the property, using :of => <attribute_name>"
|
|
9
|
+
attrs = [attrs].flatten #(make sure it's an array)
|
|
10
|
+
|
|
11
|
+
raise ArgumentError, "you must provide either :in => [<value1>, <value2>..] or :as => <value>" unless opts[:in] || opts[:as]
|
|
12
|
+
allowed_values = opts[:in] || [opts[:as]]
|
|
13
|
+
|
|
14
|
+
args = attrs + [opts]
|
|
15
|
+
validates_each(*args) do |record, attr, attachment|
|
|
16
|
+
if attachment
|
|
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)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def expected_values_string(allowed_values)
|
|
28
|
+
if allowed_values.is_a?(Range)
|
|
29
|
+
"between #{allowed_values.first} and #{allowed_values.last}"
|
|
30
|
+
else
|
|
31
|
+
allowed_values.length > 1 ? "one of '#{allowed_values.join('\', \'')}'" : "'#{allowed_values.first.to_s}'"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -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
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Dragonfly
|
|
2
|
+
module Analysis
|
|
3
|
+
|
|
4
|
+
class FileCommandAnalyser
|
|
5
|
+
|
|
6
|
+
include Configurable
|
|
7
|
+
|
|
8
|
+
configurable_attr :file_command, "file"
|
|
9
|
+
configurable_attr :use_filesystem, false
|
|
10
|
+
configurable_attr :num_bytes_to_check, 255
|
|
11
|
+
|
|
12
|
+
def mime_type(temp_object)
|
|
13
|
+
content_type = if use_filesystem
|
|
14
|
+
`#{file_command} -b --mime '#{temp_object.path}'`
|
|
15
|
+
else
|
|
16
|
+
IO.popen("#{file_command} -b --mime -", 'r+') do |io|
|
|
17
|
+
if num_bytes_to_check
|
|
18
|
+
io.write temp_object.data[0, num_bytes_to_check]
|
|
19
|
+
else
|
|
20
|
+
io.write temp_object.data
|
|
21
|
+
end
|
|
22
|
+
io.close_write
|
|
23
|
+
io.read
|
|
24
|
+
end
|
|
25
|
+
end.split(';').first
|
|
26
|
+
content_type.strip if content_type
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Dragonfly
|
|
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
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'RMagick'
|
|
2
|
+
|
|
3
|
+
module Dragonfly
|
|
4
|
+
module Analysis
|
|
5
|
+
class RMagickAnalyser
|
|
6
|
+
|
|
7
|
+
include RMagickUtils
|
|
8
|
+
include Configurable
|
|
9
|
+
|
|
10
|
+
configurable_attr :use_filesystem, true
|
|
11
|
+
|
|
12
|
+
def width(temp_object)
|
|
13
|
+
ping_rmagick_image(temp_object) do |image|
|
|
14
|
+
image.columns
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def height(temp_object)
|
|
19
|
+
ping_rmagick_image(temp_object) do |image|
|
|
20
|
+
image.rows
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def aspect_ratio(temp_object)
|
|
25
|
+
ping_rmagick_image(temp_object) do |image|
|
|
26
|
+
image.columns.to_f / image.rows
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def portrait?(temp_object)
|
|
31
|
+
ping_rmagick_image(temp_object) do |image|
|
|
32
|
+
image.columns <= image.rows
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def landscape?(temp_object)
|
|
37
|
+
ping_rmagick_image(temp_object) do |image|
|
|
38
|
+
image.columns >= image.rows
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def depth(temp_object)
|
|
43
|
+
rmagick_image(temp_object) do |image|
|
|
44
|
+
image.depth
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def number_of_colours(temp_object)
|
|
49
|
+
rmagick_image(temp_object) do |image|
|
|
50
|
+
image.number_colors
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
alias number_of_colors number_of_colours
|
|
54
|
+
|
|
55
|
+
def format(temp_object)
|
|
56
|
+
ping_rmagick_image(temp_object) do |image|
|
|
57
|
+
image.format.downcase.to_sym
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
require 'logger'
|
|
2
|
+
require 'forwardable'
|
|
3
|
+
require 'rack'
|
|
4
|
+
|
|
5
|
+
module Dragonfly
|
|
6
|
+
class App
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
|
|
10
|
+
private :new # Hide 'new' - need to use 'instance'
|
|
11
|
+
|
|
12
|
+
def instance(name)
|
|
13
|
+
apps[name] ||= new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
alias [] instance
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def apps
|
|
21
|
+
@apps ||= {}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def initialize
|
|
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
|
+
|
|
38
|
+
extend Forwardable
|
|
39
|
+
def_delegator :datastore, :destroy
|
|
40
|
+
def_delegators :new_job, :fetch, :generate, :fetch_file
|
|
41
|
+
def_delegator :server, :call
|
|
42
|
+
|
|
43
|
+
configurable_attr :datastore do DataStorage::FileDataStore.new end
|
|
44
|
+
configurable_attr :cache_duration, 3600*24*365 # (1 year)
|
|
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
|
+
configurable_attr :secret, 'secret yo'
|
|
51
|
+
configurable_attr :log do Logger.new('/var/tmp/dragonfly.log') end
|
|
52
|
+
configurable_attr :infer_mime_type_from_file_ext, true
|
|
53
|
+
configurable_attr :content_disposition
|
|
54
|
+
configurable_attr :content_filename, Response::DEFAULT_FILENAME
|
|
55
|
+
|
|
56
|
+
attr_reader :analyser
|
|
57
|
+
attr_reader :processor
|
|
58
|
+
attr_reader :encoder
|
|
59
|
+
attr_reader :generator
|
|
60
|
+
attr_reader :server
|
|
61
|
+
|
|
62
|
+
configuration_method :analyser
|
|
63
|
+
configuration_method :processor
|
|
64
|
+
configuration_method :encoder
|
|
65
|
+
configuration_method :generator
|
|
66
|
+
|
|
67
|
+
attr_accessor :job_definitions
|
|
68
|
+
|
|
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)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def endpoint(job=nil, &block)
|
|
91
|
+
block ? RoutedEndpoint.new(self, &block) : JobEndpoint.new(job)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def job(name, &block)
|
|
95
|
+
job_definitions.add(name, &block)
|
|
96
|
+
end
|
|
97
|
+
configuration_method :job
|
|
98
|
+
|
|
99
|
+
def store(object, opts={})
|
|
100
|
+
temp_object = object.is_a?(TempObject) ? object : TempObject.new(object)
|
|
101
|
+
temp_object.extract_attributes_from(opts)
|
|
102
|
+
datastore.store(temp_object, opts)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def register_mime_type(format, mime_type)
|
|
106
|
+
registered_mime_types[file_ext_string(format)] = mime_type
|
|
107
|
+
end
|
|
108
|
+
configuration_method :register_mime_type
|
|
109
|
+
|
|
110
|
+
def registered_mime_types
|
|
111
|
+
@registered_mime_types ||= Rack::Mime::MIME_TYPES.dup
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def mime_type_for(format)
|
|
115
|
+
registered_mime_types[file_ext_string(format)]
|
|
116
|
+
end
|
|
117
|
+
|
|
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
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def mount_path
|
|
127
|
+
url_path_prefix.blank? ? '/' : url_path_prefix
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def url_for(job, *args)
|
|
131
|
+
if (args.length == 1 && args.first.kind_of?(Hash)) || args.empty?
|
|
132
|
+
opts = args.first ? args.first.dup : {}
|
|
133
|
+
host = opts.delete(:host) || url_host
|
|
134
|
+
suffix = opts.delete(:suffix) || url_suffix
|
|
135
|
+
suffix = suffix.call(job) if suffix.respond_to?(:call)
|
|
136
|
+
path_prefix = opts.delete(:path_prefix) || url_path_prefix
|
|
137
|
+
path = "#{host}#{path_prefix}#{job.to_path}#{suffix}"
|
|
138
|
+
query = opts
|
|
139
|
+
query.merge!(server.required_params_for(job)) if protect_from_dos_attacks
|
|
140
|
+
path << "?#{Rack::Utils.build_query(query)}" if query.any?
|
|
141
|
+
path
|
|
142
|
+
else
|
|
143
|
+
# Deprecation stuff - will be removed!!!
|
|
144
|
+
case args[0]
|
|
145
|
+
when /^(\d+)?x(\d+)?/
|
|
146
|
+
log.warn("DEPRECATED USE OF url_for and will be removed in the future - please use thumb(#{args.map{|a|a.inspect}.join(', ')}).url")
|
|
147
|
+
args[1] ? job.thumb(args[0], args[1]).url : job.thumb(args[0]).url
|
|
148
|
+
when :gif, :png, :jpg, :jpeg
|
|
149
|
+
log.warn("DEPRECATED USE OF url_for and will be removed in the future - please use encode(#{args.first.inspect}).url")
|
|
150
|
+
job.encode(args[0]).url
|
|
151
|
+
else
|
|
152
|
+
raise "DEPRECATED USE OF url_for - will be removed in future versions - please consult the docs"
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def define_macro(mod, macro_name)
|
|
158
|
+
already_extended = (class << mod; self; end).included_modules.include?(ActiveModelExtensions)
|
|
159
|
+
mod.extend(ActiveModelExtensions) unless already_extended
|
|
160
|
+
mod.register_dragonfly_app(macro_name, self)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def define_macro_on_include(mod, macro_name)
|
|
164
|
+
app = self
|
|
165
|
+
(class << mod; self; end).class_eval do
|
|
166
|
+
alias included_without_dragonfly included
|
|
167
|
+
define_method :included_with_dragonfly do |mod|
|
|
168
|
+
included_without_dragonfly(mod)
|
|
169
|
+
app.define_macro(mod, macro_name)
|
|
170
|
+
end
|
|
171
|
+
alias included included_with_dragonfly
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
private
|
|
176
|
+
|
|
177
|
+
def file_ext_string(format)
|
|
178
|
+
'.' + format.to_s.downcase.sub(/^.*\./,'')
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
end
|
|
182
|
+
end
|