Permalink
Browse files

moved dynamic view resizing into url_for_image_column helper

git-svn-id: http://opensvn.csie.org/rails_file_column/plugins/file_column/trunk@37 6a5db2c9-b104-0410-84e5-917aad89f9d9
  • Loading branch information...
skanthak
skanthak committed Nov 23, 2005
1 parent 5cd26e1 commit d74ae32de6f5ab22036eb03d3198caf248bf6ecb
Showing with 158 additions and 41 deletions.
  1. +4 −3 CHANGELOG
  2. +1 −0 Rakefile
  3. +52 −17 lib/file_column_helper.rb
  4. +30 −15 lib/magick_file_column.rb
  5. +6 −0 test/abstract_unit.rb
  6. +1 −6 test/file_column_helper_test.rb
  7. +43 −0 test/magick_test.rb
  8. +21 −0 test/magick_view_only_test.rb
View
@@ -1,10 +1,11 @@
*svn*
* allow for directories in file_column dirs as well
* use subdirs for versions instead of fiddling with filename
- * implemented dynamic resizing of images from views
+ * url_for_image_column_helper for dynamic resizing of images from views
* new "crop" feature [Sean Treadway]
- * do not require model objects to be stored in instance variable in
- url_for_file_column helper
+ * url_for_file_column helper: do not require model objects to be stored in
+ instance variables
+
0.3.1
* make object with file_columns serializable
View
@@ -32,4 +32,5 @@ task :test do
sh "cd test; ruby file_column_test.rb"
sh "cd test; ruby file_column_helper_test.rb"
sh "cd test; ruby magick_test.rb"
+ sh "cd test; ruby magick_view_only_test.rb"
end
View
@@ -42,37 +42,72 @@ def file_column_field(object, method, options={})
#
# If there is currently no uploaded file stored in the object's column this method will
# return +nil+.
+ def url_for_file_column(object, method, subdir=nil)
+ case object
+ when String, Symbol
+ object = instance_variable_get("@#{object.to_s}")
+ end
+ relative_path = object.send("#{method}_relative_path", subdir)
+ return nil unless relative_path
+ url = ""
+ url << @request.relative_url_root.to_s << "/"
+ url << object.send("#{method}_options")[:base_url] << "/"
+ url << relative_path
+ end
+
+ # Same as +url_for_file_colum+ but allows you to access different versions
+ # of the image that have been processed by RMagick.
#
- # If your +options+ parameter contains a key <tt>:version</tt> this will
+ # If your +options+ parameter is non-nil this will
# access a different version of an image that will be produced by
- # RMagick. You can use the following types of versions:
+ # RMagick. You can use the following types for +options+:
#
- # * <tt>:version => :symbol</tt> will select a version defined in the model
- # via FileColumn::Magick's version feature.
- # * <tt>:version => geometry_string</tt> will dynamically create an
+ # * a <tt>:symbol</tt> will select a version defined in the model
+ # via FileColumn::Magick's <tt>:versions</tt> feature.
+ # * a <tt>geometry_string</tt> will dynamically create an
# image resized as specified by <tt>geometry_string</tt>. The image will
# be stored so that it does not have to be recomputed the next time the
# same version string is used.
- # * <tt>:version => some_hash</tt> will dynamically create an image
+ # * <tt>some_hash</tt> will dynamically create an image
# that is created according to the options in <tt>some_hash</tt>. This
# accepts exactly the same options as Magick's version feature.
#
- # Note that if you pass a string or a symbol as the +object+ parameter,
- # the file_column will be looked up in instance variable named +object+.
- def url_for_file_column(object, method, options=nil)
+ # The version produces by RMagick will be stored in a special sub-directories.
+ # The directories name will be derived from the options you specify but if want
+ # to set it yourself, you can use the <tt>:name => name</tt> option.
+ #
+ # Examples:
+ #
+ # <%= url_for_image_column @entry, "image", "640x480" %>
+ #
+ # will produce an URL like this
+ #
+ # /entry/image/42/bdn19n/filename.jpg
+ # # "640x480".hash.abs.to_s(36) == "bdn19n"
+ #
+ # and
+ #
+ # <%= url_for_image_column @entry, "image",
+ # :size => "50x50", :crop => "1:1", :name => "thumb" %>
+ #
+ # will produce something like this:
+ #
+ # /entry/image/42/thumb/filename.jpg
+ #
+ # Hint: If you are using the same geometry string / options hash multiple times, you should
+ # define it in a helper to stay with DRY. Another option is to define it in the model via
+ # FileColumn::Magick's <tt>:versions</tt> feature and then refer to it via a symbol.
+ #
+ # If there is currently no image uploaded, this method will return +nil+.
+ def url_for_image_column(object, method, options=nil)
case object
when String, Symbol
object = instance_variable_get("@#{object.to_s}")
end
subdir = nil
- if options and options[:version]
- subdir = object.send("#{method}_state").create_magick_version_if_needed(options[:version])
+ if options
+ subdir = object.send("#{method}_state").create_magick_version_if_needed(options)
end
- relative_path = object.send("#{method}_relative_path", subdir)
- return nil unless relative_path
- url = ""
- url << @request.relative_url_root.to_s << "/"
- url << object.send("#{method}_options")[:base_url] << "/"
- url << relative_path
+ url_for_file_column(object, method, subdir)
end
end
View
@@ -19,7 +19,7 @@ def transform_with_magick
resize_image(img, version_options, absolute_path(dirname))
end
end
- if options[:magick][:geometry] or options[:magick][:crop]
+ if options[:magick][:size] or options[:magick][:crop]
resize_image(img, options[:magick], absolute_path)
end
@@ -28,6 +28,16 @@ def transform_with_magick
end
def create_magick_version_if_needed(version)
+ # RMagick might not have been loaded so far.
+ # We do not want to require it on every call of this method
+ # as this might be fairly expensive, so we just try if ::Magick
+ # exists and require it if not.
+ begin
+ ::Magick
+ rescue NameError
+ require 'RMagick'
+ end
+
if version.is_a?(Symbol)
version_options = options[:magick][:versions][version]
else
@@ -54,7 +64,7 @@ def has_magick_errors?
def needs_resize?
options[:magick] and just_uploaded? and
- (options[:magick][:geometry] or options[:magick][:versions])
+ (options[:magick][:size] or options[:magick][:versions])
end
def resize_image(img, img_options, dest_path)
@@ -66,8 +76,8 @@ def resize_image(img, img_options, dest_path)
[img.rows, h].min)
end
- if img_options[:geometry]
- img = img.change_geometry(img_options[:geometry]) do |c, r, i|
+ if img_options[:size]
+ img = img.change_geometry(img_options[:size]) do |c, r, i|
i.resize(c, r)
end
end
@@ -88,23 +98,23 @@ def resize_image(img, img_options, dest_path)
# after a new file is assigned to the file_column attribute.
#
# To resize the uploaded image according to an imagemagick geometry
- # string, just use the <tt>:geometry</tt> option:
+ # string, just use the <tt>:size</tt> option:
#
- # file_column :image, :magick => {:geometry => "800x600>"}
+ # file_column :image, :magick => {:size => "800x600>"}
#
# You can also create additional versions of your image, for example
# thumb-nails, like this:
# file_column :image, :magick => {:versions => {
- # "thumb" => {:geometry => "50x50"},
- # "medium" => {:geometry => "640x480>"}
+ # "thumb" => {:size => "50x50"},
+ # "medium" => {:size => "640x480>"}
# }
#
# If you wish to crop your images with a size ratio before scaling
# them according to your version geometry, you can use the :crop directive.
# file_column :image, :magick => {:versions => {
- # "square" => {:crop => "1:1", :geometry => "50x50"},
- # "screen" => {:crop => "4:3", :geometry => "640x480>"},
- # "widescreen" => {:crop => "16:9", :geometry => "640x360!"},
+ # "square" => {:crop => "1:1", :size => "50x50"},
+ # "screen" => {:crop => "4:3", :size => "640x480>"},
+ # "widescreen" => {:crop => "16:9", :size => "640x360!"},
# }
# }
#
@@ -121,6 +131,7 @@ module Magick
def self.file_column(klass, attr, options) # :nodoc:
require 'RMagick'
+ options[:magick] = process_options(options[:magick],false) if options[:magick]
if options[:magick][:versions]
options[:magick][:versions].each_pair do |name, value|
options[:magick][:versions][name] = process_options(value)
@@ -147,16 +158,20 @@ def self.file_column(klass, attr, options) # :nodoc:
end
- def self.process_options(options)
- options = {:geometry => options } if options.kind_of?(String)
- unless options[:name]
+ def self.process_options(options,create_name=true)
+ options = {:size => options } if options.kind_of?(String)
+ if options[:geometry]
+ options[:size] = options.delete(:geometry)
+ end
+ if options[:name].nil? and create_name
hash = 0
- for key in [:geometry, :crop]
+ for key in [:size, :crop]
hash = hash ^ options[key].hash if options[key]
end
options[:name] = hash.abs.to_s(36)
end
options
end
+
end
end
View
@@ -22,6 +22,12 @@ class ActiveRecord::Base
end
+class RequestMock
+ def relative_url_root
+ ""
+ end
+end
+
class Test::Unit::TestCase
private
@@ -1,12 +1,6 @@
require 'abstract_unit'
require 'fixtures/entry'
-class RequestMock
- def relative_url_root
- ""
- end
-end
-
class UrlForFileColumnTest < Test::Unit::TestCase
include FileColumnHelper
@@ -50,3 +44,4 @@ def test_url_for_file_column_should_return_nil_on_no_uploaded_file
assert_nil url_for_file_column(e, "image")
end
end
+
View
@@ -169,3 +169,46 @@ def test_should_crop_image_on_upload
end
end
+
+class UrlForImageColumnTest < AbstractRMagickTest
+ include FileColumnHelper
+
+ def setup
+ Entry.file_column :image, :magick => {
+ :versions => {:thumb => {:size => "50x50", :name => "thumb" } }
+ }
+ @request = RequestMock.new
+ end
+
+ def test_should_use_version_on_symbol_option
+ e = Entry.new(:image => upload("skanthak.png"))
+
+ url = url_for_image_column(e, "image", :thumb)
+ assert_match %r{^/entry/image/tmp/.+/thumb/skanthak.png$}, url
+ end
+
+ def test_should_use_string_as_size
+ e = Entry.new(:image => upload("skanthak.png"))
+
+ url = url_for_image_column(e, "image", "50x50")
+
+ assert_match %r{^/entry/image/tmp/.+/.+/skanthak.png$}, url
+
+ url =~ /\/([^\/]+)\/skanthak.png$/
+ dirname = $1
+
+ assert_max_image_size read_image(e.image(dirname)), 50
+ end
+
+ def test_should_accept_version_hash
+ e = Entry.new(:image => upload("skanthak.png"))
+
+ url = url_for_image_column(e, "image", :size => "50x50", :crop => "1:1", :name => "small")
+
+ assert_match %r{^/entry/image/tmp/.+/small/skanthak.png$}, url
+
+ img = read_image(e.image("small"))
+ assert_equal 50, img.rows
+ assert_equal 50, img.columns
+ end
+end
@@ -0,0 +1,21 @@
+require 'abstract_unit'
+require 'fixtures/entry'
+
+class RMagickViewOnlyTest < Test::Unit::TestCase
+ include FileColumnHelper
+
+ def setup
+ Entry.file_column :image
+ @request = RequestMock.new
+ end
+
+ def teardown
+ FileUtils.rm_rf File.dirname(__FILE__)+"/public/entry/"
+ end
+
+ def test_url_for_image_column_without_model_versions
+ e = Entry.new(:image => upload("skanthak.png"))
+
+ assert_nothing_raised { url_for_image_column e, "image", "50x50" }
+ end
+end

0 comments on commit d74ae32

Please sign in to comment.