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,66 @@
|
|
|
1
|
+
require 'tempfile'
|
|
2
|
+
|
|
3
|
+
Given /^we are using the app for (\w+)$/ do |app_name|
|
|
4
|
+
$app = Dragonfly[app_name.to_sym]
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
Given /^a stored file "(.+?)"$/ do |name|
|
|
8
|
+
file = File.new(File.dirname(__FILE__) + "/../../samples/#{name}")
|
|
9
|
+
uid = $app.store(file)
|
|
10
|
+
TEMP_FILES[name] = uid
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
Given /^a stored image "(.+?)" with dimensions (\d+)x(\d+)$/ do |name, width, height|
|
|
14
|
+
tempfile = Tempfile.new(name)
|
|
15
|
+
`convert -resize #{width}x#{height}! #{SAMPLE_IMAGE_PATH} #{tempfile.path}`
|
|
16
|
+
uid = $app.store(tempfile)
|
|
17
|
+
TEMP_FILES[name] = uid
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
When /^I go to the url for "(.+?)"$/ do |name|
|
|
21
|
+
uid = TEMP_FILES[name]
|
|
22
|
+
make_request $app.fetch(uid)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
When /^I go to the url for "(.+?)", with format '([^']+?)'$/ do |name, format|
|
|
26
|
+
uid = TEMP_FILES[name]
|
|
27
|
+
make_request $app.fetch(uid).encode(format)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
When /^I go to the url for "(.+?)", with format '(.+?)' and resize geometry '(.+?)'$/ do |name, format, geometry|
|
|
31
|
+
uid = TEMP_FILES[name]
|
|
32
|
+
make_request $app.fetch(uid).process(:resize, geometry).encode(format)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
When /^I go to the url for "(.+?)", with shortcut '([^']+?)'$/ do |name, geometry|
|
|
36
|
+
uid = TEMP_FILES[name]
|
|
37
|
+
make_request $app.fetch(uid).thumb(geometry)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
Then "the response should be OK" do
|
|
41
|
+
@response.status.should == 200
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
Then /the response should have mime-type '(.+?)'/ do |mime_type|
|
|
45
|
+
@response.headers['Content-Type'].should == mime_type
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
Then /^the image should have width '(.+?)'$/ do |width|
|
|
49
|
+
@response.body.should have_width(width.to_i)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
Then /^the image should have height '(.+?)'$/ do |height|
|
|
53
|
+
@response.body.should have_height(height.to_i)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
Then /^the image should have format '(.+?)'$/ do |format|
|
|
57
|
+
@response.body.should have_format(format)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
Then /^the response should have the same content as the file "([^\"]*)"$/ do |name|
|
|
61
|
+
if RUBY_VERSION =~ /^1\.8/
|
|
62
|
+
@response.body.should == $app.fetch(TEMP_FILES[name]).data
|
|
63
|
+
else
|
|
64
|
+
@response.body.force_encoding('BINARY').should == $app.fetch(TEMP_FILES[name]).data.force_encoding('BINARY')
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
RAILS_APP_NAME = 'tmp_app'
|
|
2
|
+
FIXTURES_PATH = ROOT_PATH + "/fixtures"
|
|
3
|
+
GEMFILES = {
|
|
4
|
+
'2.3.5' => ROOT_PATH + '/Gemfile.rails.2.3.5',
|
|
5
|
+
'3.0.3' => ROOT_PATH + '/Gemfile',
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
def fixture_path(version)
|
|
9
|
+
"#{FIXTURES_PATH}/rails_#{version}"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def app_path(version)
|
|
13
|
+
"#{fixture_path(version)}/#{RAILS_APP_NAME}"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
##############################################################################
|
|
17
|
+
|
|
18
|
+
{
|
|
19
|
+
'2.3.5' => "BUNDLE_GEMFILE=#{GEMFILES['2.3.5']} rails #{RAILS_APP_NAME} -m template.rb",
|
|
20
|
+
'3.0.3' => "BUNDLE_GEMFILE=#{GEMFILES['3.0.3']} bundle exec rails new #{RAILS_APP_NAME} -m template.rb"
|
|
21
|
+
}.each do |version, rails_command|
|
|
22
|
+
|
|
23
|
+
Given /^a Rails #{version} application set up for using dragonfly$/ do
|
|
24
|
+
raise "Problem setting up Rails app" unless `
|
|
25
|
+
cd #{fixture_path(version)} &&
|
|
26
|
+
rm -rf #{RAILS_APP_NAME} &&
|
|
27
|
+
#{rails_command}`
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
Then /^the (.+) cucumber features in my Rails (.+) app should pass$/ do |filename, version|
|
|
33
|
+
puts "\n*** RUNNING FEATURES IN THE RAILS APP... ***\n"
|
|
34
|
+
path = File.join(fixture_path(version), RAILS_APP_NAME)
|
|
35
|
+
`cd #{path} && BUNDLE_GEMFILE=#{GEMFILES[version]} RAILS_ENV=cucumber rake db:migrate`
|
|
36
|
+
features_passed = system "cd #{path} && BUNDLE_GEMFILE=#{GEMFILES[version]} cucumber features/#{filename}.feature"
|
|
37
|
+
puts "\n*** FINISHED RUNNING FEATURES IN THE RAILS APP ***\n"
|
|
38
|
+
raise "Features failed" unless features_passed
|
|
39
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
|
|
2
|
+
require 'dragonfly'
|
|
3
|
+
require 'spec/expectations'
|
|
4
|
+
require 'test/unit/assertions'
|
|
5
|
+
require File.dirname(__FILE__) + '/../../spec/image_matchers.rb'
|
|
6
|
+
|
|
7
|
+
ROOT_PATH = File.expand_path(File.dirname(__FILE__) + "/../..")
|
|
8
|
+
|
|
9
|
+
# A hash of <name for reference> => <dragonfly uid> pairs
|
|
10
|
+
TEMP_FILES = {}
|
|
11
|
+
|
|
12
|
+
Dragonfly[:images].configure_with(:imagemagick)
|
|
13
|
+
Dragonfly[:files].configure do |c|
|
|
14
|
+
c.analyser.register(Dragonfly::Analysis::FileCommandAnalyser)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
SAMPLE_IMAGE_PATH = File.dirname(__FILE__)+'/../../samples/beach.png'
|
|
18
|
+
|
|
19
|
+
Before do
|
|
20
|
+
# Remove temporary images
|
|
21
|
+
TEMP_FILES.each do |name, uid|
|
|
22
|
+
$app.datastore.destroy(uid)
|
|
23
|
+
TEMP_FILES.delete(name)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
AfterStep do |scenario|
|
|
28
|
+
Dir["#{ROOT_PATH}/Gemfile*.lock"].each{|f| FileUtils.rm_f(f) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
module MyHelpers
|
|
32
|
+
|
|
33
|
+
def make_request(job)
|
|
34
|
+
request = Rack::MockRequest.new($app)
|
|
35
|
+
@response = request.get(job.url)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
World(MyHelpers)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Feature: champion adds cover images to his albums
|
|
2
|
+
In order to be a champion
|
|
3
|
+
A user adds an image to his album
|
|
4
|
+
|
|
5
|
+
Scenario: Add and view image
|
|
6
|
+
When I go to the new album page
|
|
7
|
+
And I attach the file "../../../samples/beach.png" to "album[cover_image]"
|
|
8
|
+
And I press "Create"
|
|
9
|
+
Then I should see "successfully created"
|
|
10
|
+
And I should see "Look at this cover image!"
|
|
11
|
+
When I look at the generated beach image
|
|
12
|
+
And I should see a PNG image of size 200x100
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
When /^I look at the generated (.+) image$/ do |image_name|
|
|
2
|
+
page.body =~ %r{src="(/media[^"]+?)"}
|
|
3
|
+
url = $1
|
|
4
|
+
visit(url)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
Then /^I should see a (.+) image of size (.+)$/ do |format, size|
|
|
8
|
+
tempfile = Tempfile.new('wicked')
|
|
9
|
+
page.body.force_encoding('UTF-8').encode! if page.body.respond_to?(:force_encoding) # For some reason need this on Ruby 1.9.2
|
|
10
|
+
tempfile.write page.body
|
|
11
|
+
tempfile.close
|
|
12
|
+
output = `identify #{tempfile.path}`.split(' ')
|
|
13
|
+
output[1].should == format
|
|
14
|
+
output[2].should == size
|
|
15
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module NavigationHelpers
|
|
2
|
+
def path_to(page_name)
|
|
3
|
+
case page_name
|
|
4
|
+
when "the new album page"
|
|
5
|
+
'/albums/new'
|
|
6
|
+
when /^the image for text "(.+)", size "(.+)"$/
|
|
7
|
+
"/text/#{$1}/#{$2}"
|
|
8
|
+
else
|
|
9
|
+
raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
|
|
10
|
+
"Now, go and add a mapping in #{__FILE__}"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
World(NavigationHelpers)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
gem 'rack-cache', :lib => 'rack/cache'
|
|
2
|
+
gem 'cucumber'
|
|
3
|
+
generate 'cucumber'
|
|
4
|
+
|
|
5
|
+
generate 'scaffold albums cover_image_uid:string'
|
|
6
|
+
rake 'db:migrate'
|
|
7
|
+
|
|
8
|
+
# Copy over all files from the template dir
|
|
9
|
+
files_dir = File.expand_path(File.dirname(__FILE__) + '/../../files')
|
|
10
|
+
run "cp -r #{files_dir}/** ."
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
gem 'rack-cache', :require => 'rack/cache'
|
|
2
|
+
|
|
3
|
+
gem 'capybara'
|
|
4
|
+
gem 'cucumber-rails'
|
|
5
|
+
gem 'cucumber', '0.8.5'
|
|
6
|
+
|
|
7
|
+
generate 'cucumber:install'
|
|
8
|
+
|
|
9
|
+
generate 'scaffold albums cover_image_uid:string'
|
|
10
|
+
rake 'db:migrate'
|
|
11
|
+
|
|
12
|
+
# Copy over all files from the template dir
|
|
13
|
+
files_dir = File.expand_path(File.dirname(__FILE__) + '/../files')
|
|
14
|
+
run "cp -r #{files_dir}/** ."
|
|
15
|
+
|
|
16
|
+
route <<ROUTES
|
|
17
|
+
match '/text/:text/:size' => Dragonfly[:images].endpoint{|params, app|
|
|
18
|
+
app.generate(:text, params[:text]).thumb(params[:size])
|
|
19
|
+
}
|
|
20
|
+
ROUTES
|
data/irbrc.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require "rubygems"
|
|
2
|
+
require "bundler/setup"
|
|
3
|
+
require File.dirname(__FILE__) + '/lib/dragonfly'
|
|
4
|
+
APP = Dragonfly[:images].configure_with(:imagemagick)
|
|
5
|
+
|
|
6
|
+
# available_uids = `find #{APP.datastore.root_path} ! -type d`.split("\n").map do |file|
|
|
7
|
+
# file.sub("#{APP.datastore.root_path}/", '')
|
|
8
|
+
# end
|
|
9
|
+
|
|
10
|
+
puts "Loaded stuff from dragonfly irbrc"
|
|
11
|
+
# puts "\nAvailable uids:\n"
|
|
12
|
+
# puts available_uids
|
|
13
|
+
puts "\nAvailable sample images:\n"
|
|
14
|
+
puts Dir['samples/*']
|
|
15
|
+
puts "\nAvailable constants:\n"
|
|
16
|
+
puts "APP"
|
|
17
|
+
puts
|
data/lib/dragonfly.rb
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# AUTOLOAD EVERYTHING IN THE DRAGONFLY DIRECTORY TREE
|
|
2
|
+
|
|
3
|
+
# The convention is that dirs are modules
|
|
4
|
+
# so declare them here and autoload any modules/classes inside them
|
|
5
|
+
# All paths here are absolute
|
|
6
|
+
def camelize(path)
|
|
7
|
+
# e.g. 'test/this_one' => Test::ThisOne
|
|
8
|
+
"#{path}".
|
|
9
|
+
chomp('/').
|
|
10
|
+
gsub('/','::').
|
|
11
|
+
gsub(/([^a-z])(\w)/){ "#{$1}#{$2.upcase}" }.
|
|
12
|
+
gsub('_','').
|
|
13
|
+
sub(/^(\w)/){ $1.upcase }
|
|
14
|
+
end
|
|
15
|
+
def autoload_files_in_dir(path, namespace)
|
|
16
|
+
# Define the module
|
|
17
|
+
eval("module #{namespace}; end")
|
|
18
|
+
# Autoload modules/classes in that module
|
|
19
|
+
Dir.glob("#{path}/*.rb").each do |file|
|
|
20
|
+
file = File.expand_path(file)
|
|
21
|
+
sub_const_name = camelize( File.basename(file, '.rb') )
|
|
22
|
+
eval("#{namespace}.autoload('#{sub_const_name}', '#{file}')")
|
|
23
|
+
end
|
|
24
|
+
# Recurse on subdirectories
|
|
25
|
+
Dir.glob("#{path}/*/").each do |dir|
|
|
26
|
+
sub_namespace = camelize( File.basename(dir) )
|
|
27
|
+
autoload_files_in_dir(dir, "#{namespace}::#{sub_namespace}")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
autoload_files_in_dir("#{File.dirname(__FILE__)}/dragonfly", 'Dragonfly')
|
|
32
|
+
|
|
33
|
+
require File.dirname(__FILE__) + '/dragonfly/core_ext/object'
|
|
34
|
+
require File.dirname(__FILE__) + '/dragonfly/core_ext/string'
|
|
35
|
+
require File.dirname(__FILE__) + '/dragonfly/core_ext/symbol'
|
|
36
|
+
|
|
37
|
+
module Dragonfly
|
|
38
|
+
class << self
|
|
39
|
+
|
|
40
|
+
def [](*args)
|
|
41
|
+
App[*args]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
|
|
3
|
+
module Dragonfly
|
|
4
|
+
module ActiveModelExtensions
|
|
5
|
+
|
|
6
|
+
class Attachment
|
|
7
|
+
|
|
8
|
+
extend Forwardable
|
|
9
|
+
def_delegators :job,
|
|
10
|
+
:data, :to_file, :file, :tempfile, :path,
|
|
11
|
+
:process, :encode, :analyse,
|
|
12
|
+
:meta, :meta=,
|
|
13
|
+
:url
|
|
14
|
+
|
|
15
|
+
def initialize(app, parent_model, attribute_name)
|
|
16
|
+
@app, @parent_model, @attribute_name = app, parent_model, attribute_name
|
|
17
|
+
self.extend app.analyser.analysis_methods
|
|
18
|
+
self.extend app.job_definitions
|
|
19
|
+
self.uid = parent_uid
|
|
20
|
+
self.job = app.fetch(uid) if uid
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def assign(value)
|
|
24
|
+
if value.nil?
|
|
25
|
+
self.job = nil
|
|
26
|
+
reset_magic_attributes
|
|
27
|
+
else
|
|
28
|
+
self.job = case value
|
|
29
|
+
when Job then value.dup
|
|
30
|
+
when self.class then value.job.dup
|
|
31
|
+
else app.new_job(value)
|
|
32
|
+
end
|
|
33
|
+
set_magic_attributes
|
|
34
|
+
end
|
|
35
|
+
set_uid_and_parent_uid(nil)
|
|
36
|
+
value
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def destroy!
|
|
40
|
+
destroy_previous!
|
|
41
|
+
destroy_content(uid) if uid
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def save!
|
|
45
|
+
sync_with_parent!
|
|
46
|
+
destroy_previous!
|
|
47
|
+
if job && !uid
|
|
48
|
+
set_uid_and_parent_uid job.store(
|
|
49
|
+
:meta => {
|
|
50
|
+
:model_class => parent_model.class.name,
|
|
51
|
+
:model_attachment => attribute_name
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
self.job = job.to_fetched_job(uid)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def to_value
|
|
59
|
+
self if job
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def analyse(meth, *args)
|
|
63
|
+
has_magic_attribute_for?(meth) ? magic_attribute_for(meth) : job.send(meth)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
[:size, :ext, :name].each do |meth|
|
|
67
|
+
define_method meth do
|
|
68
|
+
analyse(meth)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def name=(name)
|
|
73
|
+
job.name = name
|
|
74
|
+
set_magic_attribute(:name, name) if has_magic_attribute_for?(:name)
|
|
75
|
+
name
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def process!(*args)
|
|
79
|
+
assign(process(*args))
|
|
80
|
+
self
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def encode!(*args)
|
|
84
|
+
assign(encode(*args))
|
|
85
|
+
self
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
protected
|
|
89
|
+
|
|
90
|
+
attr_reader :job
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def destroy_content(uid)
|
|
95
|
+
app.datastore.destroy(uid)
|
|
96
|
+
rescue DataStorage::DataNotFound => e
|
|
97
|
+
app.log.warn("*** WARNING ***: tried to destroy data with uid #{uid}, but got error: #{e}")
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def destroy_previous!
|
|
101
|
+
if previous_uid
|
|
102
|
+
destroy_content(previous_uid)
|
|
103
|
+
self.previous_uid = nil
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def sync_with_parent!
|
|
108
|
+
# If the parent uid has been set manually
|
|
109
|
+
if uid != parent_uid
|
|
110
|
+
self.uid = parent_uid
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def set_uid_and_parent_uid(uid)
|
|
115
|
+
self.uid = uid
|
|
116
|
+
self.parent_uid = uid
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def parent_uid=(uid)
|
|
120
|
+
parent_model.send("#{attribute_name}_uid=", uid)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def parent_uid
|
|
124
|
+
parent_model.send("#{attribute_name}_uid")
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
attr_reader :app, :parent_model, :attribute_name
|
|
128
|
+
attr_writer :job
|
|
129
|
+
attr_accessor :previous_uid
|
|
130
|
+
attr_reader :uid
|
|
131
|
+
|
|
132
|
+
def uid=(uid)
|
|
133
|
+
self.previous_uid = @uid if @uid
|
|
134
|
+
@uid = uid
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def allowed_magic_attributes
|
|
138
|
+
app.analyser.analysis_method_names + [:size, :ext, :name]
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def magic_attributes
|
|
142
|
+
@magic_attributes ||= parent_model.public_methods.select { |name|
|
|
143
|
+
name.to_s =~ /^#{attribute_name}_(.+)$/ && allowed_magic_attributes.include?($1.to_sym)
|
|
144
|
+
}.map{|name| name.to_s.sub("#{attribute_name}_", '').to_sym }
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def set_magic_attribute(property, value)
|
|
148
|
+
parent_model.send("#{attribute_name}_#{property}=", value)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def set_magic_attributes
|
|
152
|
+
magic_attributes.each{|property| set_magic_attribute(property, job.send(property)) }
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def reset_magic_attributes
|
|
156
|
+
magic_attributes.each{|property| set_magic_attribute(property, nil) }
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def has_magic_attribute_for?(property)
|
|
160
|
+
magic_attributes.include?(property.to_sym)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def magic_attribute_for(property)
|
|
164
|
+
parent_model.send("#{attribute_name}_#{property}")
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|