| 1 | module FileColumn # :nodoc: |
|---|
| 2 | |
|---|
| 3 | class BaseUploadedFile # :nodoc: |
|---|
| 4 | def transform_with_magick |
|---|
| 5 | if needs_resize? |
|---|
| 6 | begin |
|---|
| 7 | img = ::Magick::Image::read(absolute_path).first |
|---|
| 8 | rescue ::Magick::ImageMagickError |
|---|
| 9 | @magick_errors ||= [] |
|---|
| 10 | @magick_errors << "invalid image" |
|---|
| 11 | return |
|---|
| 12 | end |
|---|
| 13 | |
|---|
| 14 | if @options[:magick][:versions] |
|---|
| 15 | @options[:magick][:versions].each_pair do |name, version_options| |
|---|
| 16 | resize_image(img, version_options[:geometry], absolute_path(name)) |
|---|
| 17 | end |
|---|
| 18 | end |
|---|
| 19 | if @options[:magick][:geometry] |
|---|
| 20 | resize_image(img, @options[:magick][:geometry], absolute_path) |
|---|
| 21 | end |
|---|
| 22 | end |
|---|
| 23 | end |
|---|
| 24 | |
|---|
| 25 | attr_reader :magick_errors |
|---|
| 26 | |
|---|
| 27 | def has_magick_errors? |
|---|
| 28 | @magick_errors and !@magick_errors.empty? |
|---|
| 29 | end |
|---|
| 30 | |
|---|
| 31 | private |
|---|
| 32 | |
|---|
| 33 | def needs_resize? |
|---|
| 34 | @options[:magick] and just_uploaded? and |
|---|
| 35 | (@options[:magick][:geometry] or@options[:magick][:versions]) |
|---|
| 36 | end |
|---|
| 37 | |
|---|
| 38 | def resize_image(img, geometry, path) |
|---|
| 39 | new_img = img.change_geometry(geometry) do |c, r, i| |
|---|
| 40 | i.resize(c, r) |
|---|
| 41 | end |
|---|
| 42 | new_img.write path |
|---|
| 43 | end |
|---|
| 44 | end |
|---|
| 45 | |
|---|
| 46 | # If you are using file_column to upload images, you can |
|---|
| 47 | # directly process the images with RMagick, |
|---|
| 48 | # a ruby extension |
|---|
| 49 | # for accessing the popular imagemagick libraries. You can find |
|---|
| 50 | # more information about RMagick at http://rmagick.rubyforge.org. |
|---|
| 51 | # |
|---|
| 52 | # You can control what to do by adding a <tt>:magick</tt> option |
|---|
| 53 | # to your options hash. All operations are performed immediately |
|---|
| 54 | # after a new file is assigned to the file_column attribute. |
|---|
| 55 | # |
|---|
| 56 | # To resize the uploaded image according to an imagemagick geometry |
|---|
| 57 | # string, just use the <tt>:geometry</tt> option: |
|---|
| 58 | # |
|---|
| 59 | # file_column :image, :magick => {:geometry => "800x600>"} |
|---|
| 60 | # |
|---|
| 61 | # You can also create additional versions of your image, for example |
|---|
| 62 | # thumb-nails, like this: |
|---|
| 63 | # file_column :image, :magick => {:versions => |
|---|
| 64 | # { "thumb" => "50x50", "medium" => "640x480>" } |
|---|
| 65 | # } |
|---|
| 66 | # |
|---|
| 67 | # These versions can later be accessed via file_column's <em>suffix</em> |
|---|
| 68 | # mechanism. So if the uploaded image was named "vancouver.jpg", you can |
|---|
| 69 | # access the additional versions like this: |
|---|
| 70 | # |
|---|
| 71 | # o.image("thumb") # produces ".../vancouver-thumb.jpg" |
|---|
| 72 | # o.image_relative_path("medium") # produces ".../vancouver-medium.jpg" |
|---|
| 73 | # |
|---|
| 74 | # The same mechanism can be used in the +url_for_file_column+ helper: |
|---|
| 75 | # |
|---|
| 76 | # <%= url_for_file_column "entry", "image", "thumb" %> |
|---|
| 77 | # |
|---|
| 78 | # <b>Note:</b> You'll need the |
|---|
| 79 | # rmagick extension installed as a gem in order to use file_column's |
|---|
| 80 | # rmagick integration. |
|---|
| 81 | module Magick |
|---|
| 82 | |
|---|
| 83 | def self.file_column(klass, attr, options) # :nodoc: |
|---|
| 84 | require 'RMagick' |
|---|
| 85 | if options[:magick][:versions] |
|---|
| 86 | options[:magick][:versions].each_pair do |name, value| |
|---|
| 87 | if value.kind_of?(String) |
|---|
| 88 | options[:magick][:versions][name] = {:geometry => value} |
|---|
| 89 | end |
|---|
| 90 | end |
|---|
| 91 | end |
|---|
| 92 | state_method = "#{attr}_state".to_sym |
|---|
| 93 | after_assign_method = "#{attr}_magick_after_assign".to_sym |
|---|
| 94 | |
|---|
| 95 | klass.send(:define_method, after_assign_method) do |
|---|
| 96 | self.send(state_method).transform_with_magick |
|---|
| 97 | end |
|---|
| 98 | |
|---|
| 99 | options[:after_assign] ||= [] |
|---|
| 100 | options[:after_assign] << after_assign_method |
|---|
| 101 | |
|---|
| 102 | klass.validate do |record| |
|---|
| 103 | state = record.send(state_method) |
|---|
| 104 | if state.has_magick_errors? |
|---|
| 105 | state.magick_errors.each do |error| |
|---|
| 106 | record.errors.add attr, error |
|---|
| 107 | end |
|---|
| 108 | end |
|---|
| 109 | end |
|---|
| 110 | end |
|---|
| 111 | |
|---|
| 112 | end |
|---|
| 113 | end |
|---|