Saturday, June 04, 2011

Take a look at that gem!

Attempting to upload an image to the refinerycms system yielded a stack trace returned to the user. In this case, refinery's images_controller is picking up an error in dragonfly.



When we try to upload an image in refinery, we get



dragonfly (0.8.5) lib/dragonfly/analysis/file_command_analyser.rb:16:in `popen'
dragonfly (0.8.5) lib/dragonfly/analysis/file_command_analyser.rb:16:in `mime_type'
dragonfly (0.8.5) lib/dragonfly/function_manager.rb:37:in `call'
dragonfly (0.8.5) lib/dragonfly/function_manager.rb:37:in `call_last'
dragonfly (0.8.5) lib/dragonfly/function_manager.rb:36:in `catch'
dragonfly (0.8.5) lib/dragonfly/function_manager.rb:36:in `call_last'
dragonfly (0.8.5) lib/dragonfly/function_manager.rb:35:in `each'
dragonfly (0.8.5) lib/dragonfly/function_manager.rb:35:in `call_last'
dragonfly (0.8.5) lib/dragonfly/analyser.rb:26:in `analyse'
dragonfly (0.8.5) lib/dragonfly/job.rb:200:in `analyse'
(eval):3:in `mime_type'
dragonfly (0.8.5) lib/dragonfly/active_model_extensions/attachment.rb:152:in `send'
dragonfly (0.8.5) lib/dragonfly/active_model_extensions/attachment.rb:152:in `set_magic_attributes'
dragonfly (0.8.5) lib/dragonfly/active_model_extensions/attachment.rb:152:in `each'
dragonfly (0.8.5) lib/dragonfly/active_model_extensions/attachment.rb:152:in `set_magic_attributes'
dragonfly (0.8.5) lib/dragonfly/active_model_extensions/attachment.rb:33:in `assign'
dragonfly (0.8.5) lib/dragonfly/active_model_extensions/class_methods.rb:22:in `image='
activerecord (3.0.7) lib/active_record/base.rb:1559:in `send'
activerecord (3.0.7) lib/active_record/base.rb:1559:in `attributes='
activerecord (3.0.7) lib/active_record/base.rb:1555:in `each'
activerecord (3.0.7) lib/active_record/base.rb:1555:in `attributes='
activerecord (3.0.7) lib/active_record/base.rb:1407:in `initialize'
activerecord (3.0.7) lib/active_record/base.rb:497:in `new'
activerecord (3.0.7) lib/active_record/base.rb:497:in `create'
refinerycms-images (0.9.9.21) app/controllers/admin/images_controller.rb:48:in `create'
view raw stack_trace hosted with ❤ by GitHub


Let's check out the top file



module Dragonfly
module Analysis
class FileCommandAnalyser
include Configurable
configurable_attr :file_command, "file"
configurable_attr :use_filesystem, false
configurable_attr :num_bytes_to_check, 255
def mime_type(temp_object)
content_type = if use_filesystem
`#{file_command} -b --mime '#{temp_object.path}'`
else
IO.popen("#{file_command} -b --mime -", 'r+') do |io|
if num_bytes_to_check
io.write temp_object.data[0, num_bytes_to_check]
else
io.write temp_object.data
end
io.close_write
io.read
end
end.split(';').first
content_type.strip if content_type
end
end
end
end

So it appears that the error has to do with the IO.popen. Since we know we wouldn't need that call if "use_filesystem" were true, and since line 9 suggests there is a configuration directive for this setting somewhere. We should try to find it.



So we go down the stack trace to the last known point the execution was in another gem. It turns out to be images_controller in the refinerycms gem.



Knowing the name of the controller , I tried some bash-fu and was presently suprised when it worked!



root@tara:~/tmp/1008583# locate images_controller.rb
/usr/lib/ruby/gems/1.8/gems/refinerycms-images-0.9.9.21/app/controllers/admin/images_controller.rb
root@tara:~/tmp/1008583# vim `locate images_controller.rb`
view raw commands0 hosted with ❤ by GitHub


None the less. There did not appear to be any configuration in that file. I went to the refinery gem root's directory and did a "grep -R dragonfly ." to flesh out any config files. I noticed "lib/refinerycms-images.rb."



# grep -R Dragonfly .
./lib/refinerycms-images.rb: app_images = Dragonfly[:images]
./lib/refinerycms-images.rb: app_images.analyser.register(Dragonfly::Analysis::ImageMagickAnalyser)
./lib/refinerycms-images.rb: app_images.analyser.register(Dragonfly::Analysis::FileCommandAnalyser)
./lib/refinerycms-images.rb: app.config.middleware.insert_after 'Rack::Lock', 'Dragonfly::Middleware', :images, '/system/images'
./lib/refinerycms-images.rb: app.config.middleware.insert_before 'Dragonfly::Middleware', 'Rack::Cache', {
./config/routes.rb: match '/system/images/*dragonfly', :to => Dragonfly[:images]
./app/controllers/admin/images_controller.rb: rescue Dragonfly::FunctionManager::UnableToHandle
view raw commands1 hosted with ❤ by GitHub


We check out the file and see the Dragonfly app initialization at line 22. We google around for the Dragonfly docs looking for a reference to where exactly the "use_filesystem" configuration directive must be set. Our search lands us on docs for Dragonfly::Analysis::FileCommandAnalyser


An example for the config is referenced which includes the directive we are looking for.


app.analyser.register(Dragonfly::Analysis::FileCommandAnalyser) do |a|
a.use_filesystem = false # defaults to true
a.file_command = '/opt/local/bin/file' # defaults to 'file'
a.num_bytes_to_check = 1024 # defaults to 255 - only applies if not using the filesystem
end

We then modify the source of lib-refinerycms.rb to include the modifications to the analyzer config.



git diff refinerycms-images.rb
diff --git a/refinerycms-images.rb b/refinerycms-images.rb
index 3fef0f7..e3d3caa 100644
--- a/refinerycms-images.rb
+++ b/refinerycms-images.rb
@@ -31,7 +31,9 @@ module Refinery
app_images.define_macro(ActiveRecord::Base, :image_accessor)
app_images.analyser.register(Dragonfly::Analysis::ImageMagickAnalyser)
- app_images.analyser.register(Dragonfly::Analysis::FileCommandAnalyser)
+ app_images.analyser.register(Dragonfly::Analysis::FileCommandAnalyser) do |a|
+ a.use_filesystem = true
+ end
# This url_suffix makes it so that dragonfly urls work in traditional
# situations where the filename and extension are required,
view raw refinery_change hosted with ❤ by GitHub


We attempt the image upload again and the upload succeeds. Now, how do I get involved in the refinerycms repo to discuss the changes with the leads? Something like this? https://github.com/resolve/refinerycms/pull/738



Right?

No comments: