lib/dynamic_image/helper.rb in dynamic_image-1.0.4 vs lib/dynamic_image/helper.rb in dynamic_image-2.0.0.beta1
- old
+ new
@@ -1,107 +1,161 @@
-require 'dynamic_image'
+# encoding: utf-8
module DynamicImage
+ # = DynamicImage Helper
+ #
+ # Provides helper methods for rendering and linking to images.
module Helper
+ # Returns the path for a DynamicImage::Model record.
+ # Takes the same options as +dynamic_image_url+
+ def dynamic_image_path(record_or_array, options={})
+ dynamic_image_url(record_or_array, { routing_type: :path }.merge(options))
+ end
- # Returns an hash consisting of the URL to the dynamic image and parsed options. This is mostly for internal use by
- # dynamic_image_tag and dynamic_image_url.
- def dynamic_image_options(image, options = {})
- options.symbolize_keys!
+ # Returns an HTML image tag for the record. If no size is given, it will
+ # render at the original size.
+ #
+ # ==== Options
+ # * <tt>:alt</tt>: If no alt text is given, it will default to the
+ # filename of the uploaded image.
+ #
+ # See +dynamic_image_url+ for info on how to size and cropping. Options
+ # supported by +polymorphic_url+ will be passed to the router. Any other
+ # options will be added as HTML attributes.
+ #
+ # ==== Examples
+ #
+ # image = Image.find(params[:id])
+ # dynamic_image_tag(image)
+ # # => <img alt="My file" height="200" src="..." width="320" />
+ # dynamic_image_tag(image, size: "100x100", alt="Avatar")
+ # # => <img alt="Avatar" height="62" src="..." width="100" />
+ def dynamic_image_tag(record_or_array, options={})
+ record = extract_record(record_or_array)
+ options = {
+ alt: image_alt(record.filename)
+ }.merge(options)
- options = {:crop => false}.merge(options)
- url_options = {:controller => "/images", :action => :render_dynamic_image, :id => image}
+ size = fit_size!(record_or_array, options)
+ url_options = options.extract!(*allowed_dynamic_image_url_options)
+ html_options = { size: size }.merge(options)
- if options[:original]
- url_options[:original] = 'original'
- options.delete(:original)
- end
+ image_tag(
+ dynamic_image_path_with_size(
+ record_or_array,
+ size,
+ url_options
+ ),
+ html_options
+ )
+ end
- # Image sizing
- if options[:size]
- new_size = Vector2d.new(options[:size])
- image_size = Vector2d.new(image.size)
+ # Returns the URL for a DynamicImage::Model record.
+ #
+ # ==== Options
+ #
+ # * <tt>:size</tt> - Desired image size, supplied as "{width}x{height}".
+ # The image will be scaled to fit. A partial size like "100x" or "x100"
+ # can be given, if you want a fixed width or height.
+ # * <tt>:crop</tt> - If true, the image will be cropped to the given size.
+ # * <tt>:upscale</tt> - By default, DynamicImage only scale images down,
+ # never up. Pass <tt>upscale: true</tt> to force upscaling.
+ #
+ # Any options supported by +polymorphic_url+ are also accepted.
+ #
+ # ==== Examples
+ #
+ # image = Image.find(params[:id])
+ # dynamic_image_url(image)
+ # # => "http://example.com/images/96...d1/300x187/1-2014062020...00.jpg"
+ # dynamic_image_url(image, size: '100x100')
+ # # => "http://example.com/images/72...c2/100x62/1-2014062020...00.jpg"
+ # dynamic_image_url(image, size: '100x100', crop: true)
+ # # => "http://example.com/images/a4...6b/100x100/1-2014062020...00.jpg"
+ def dynamic_image_url(record_or_array, options={})
+ size = fit_size!(record_or_array, options)
+ dynamic_image_url_with_size(record_or_array, size, options)
+ end
- unless options[:upscale]
- new_size.x = image_size.x if new_size.x > 0 && new_size.x > image_size.x
- new_size.y = image_size.y if new_size.y > 0 && new_size.y > image_size.y
- end
+ # Returns a path to the original uploaded file, without any processing
+ # applied. Sizing options are not supported.
+ def original_dynamic_image_path(record_or_array, options={})
+ dynamic_image_path(record_or_array, { action: :original }.merge(options))
+ end
- unless options[:crop]
- new_size = image_size.constrain_both(new_size)
- end
+ # Returns a URL to the original uploaded file, without any processing
+ # applied. Sizing options are not supported.
+ def original_dynamic_image_url(record_or_array, options={})
+ dynamic_image_url(record_or_array, { action: :original }.merge(options))
+ end
- options[:size] = new_size.round.to_s
- url_options[:size] = options[:size]
- end
- options.delete :crop
+ # Same as +dynamic_image_path+, but points to an image with any
+ # pre-cropping disabled.
+ def uncropped_dynamic_image_path(record_or_array, options={})
+ dynamic_image_path(record_or_array, { action: :uncropped }.merge(options))
+ end
- if options[:no_size_attr]
- options.delete :no_size_attr
- options.delete :size
- end
+ # Same as +dynamic_image_tag+, but renders an image with any
+ # pre-cropping disabled.
+ def uncropped_dynamic_image_tag(record_or_array, options={})
+ dynamic_image_tag(record_or_array, { action: :uncropped }.merge(options))
+ end
- # Filterset
- if options[:filterset]
- url_options[:filterset] = options[:filterset]
- options.delete :filterset
- end
+ # Same as +dynamic_image_url+, but points to an image with any
+ # pre-cropping disabled.
+ def uncropped_dynamic_image_url(record_or_array, options={})
+ dynamic_image_url(record_or_array, { action: :uncropped }.merge(options))
+ end
- # Filename
- if options[:filename]
- filename = options[:filename]
- unless filename =~ /\.[\w]{1,4}$/
- filename += "." + image.filename.split(".").last
- end
- url_options[:filename] = filename
- else
- url_options[:filename] = image.filename
- end
+ private
- # Alt attribute
- options[:alt] ||= image.name if image.name?
- options[:alt] ||= image.filename.split('.').first.capitalize
+ def allowed_dynamic_image_url_options
+ [
+ :format, :only_path, :protocol, :host, :subdomain, :domain,
+ :tld_length, :port, :anchor, :trailing_slash, :script_name,
+ :action, :routing_type
+ ]
+ end
- if options.has_key?(:only_path)
- url_options[:only_path] = options[:only_path]
- options[:only_path] = nil
- end
- if options.has_key?(:host)
- url_options[:host] = options[:host]
- options[:host] = nil
- end
+ def default_format_for_image(record)
+ Mime::Type.lookup(record.safe_content_type).to_sym
+ end
- {:url => url_for(url_options), :options => options}
+ def dynamic_image_digest(record, action, size=nil)
+ key = [action || 'show', record.id, size].compact.join('-')
+ DynamicImage.digest_verifier.generate(key)
end
- # Returns an image tag for the provided image model, works similar to the rails <tt>image_tag</tt> helper.
- #
- # The following options are supported (the rest will be forwarded to <tt>image_tag</tt>):
- #
- # * :size - Resize the image to fit these proportions. Size is given as a string with the format
- # '100x100'. Either dimension can be omitted, for example: '100x'
- # * :crop - Crop the image to the size given. (Boolean, default: <tt>false</tt>)
- # * :no_size_attr - Do not include width and height attributes in the image tag. (Boolean, default: false)
- # * :filterset - Apply the given filterset to the image
- #
- # ==== Examples
- #
- # dynamic_image_tag(@image) # Original image
- # dynamic_image_tag(@image, :size => "100x") # Will be 100px wide
- # dynamic_image_tag(@image, :size => "100x100") # Will fit within 100x100
- # dynamic_image_tag(@image, :size => "100x100", :crop => true) # Will be cropped to 100x100
- #
- def dynamic_image_tag(image, options = {})
- parsed_options = dynamic_image_options(image, options)
- image_tag(parsed_options[:url], parsed_options[:options] ).gsub(/\?[\d]+/,'').html_safe
+ def dynamic_image_path_with_size(record_or_array, size=nil, options={})
+ dynamic_image_url_with_size(record_or_array, size, { routing_type: :path }.merge(options))
end
- # Returns an url corresponding to the provided image model.
- # Special options are documented in ApplicationHelper.dynamic_image_tag, only <tt>:size</tt>, <tt>:filterset</tt> and <tt>:crop</tt> apply.
- def dynamic_image_url(image, options = {})
- parsed_options = dynamic_image_options(image, options)
- parsed_options[:url]
+ def dynamic_image_url_with_size(record_or_array, size=nil, options={})
+ record = extract_record(record_or_array)
+ options = {
+ routing_type: :url,
+ action: nil,
+ format: default_format_for_image(record),
+ size: size
+ }.merge(options)
+ options[:digest] = dynamic_image_digest(record, options[:action], options[:size])
+ polymorphic_url(record_or_array, options)
end
+
+ def fit_size!(record_or_array, options)
+ record = extract_record(record_or_array)
+ action = options[:action].try(:to_s)
+ size_opts = options.extract!(:size, :crop, :upscale)
+
+ if size_opts[:size]
+ DynamicImage::ImageSizing.new(
+ record,
+ uncropped: (action == "uncropped")
+ ).fit(size_opts[:size], size_opts).floor.to_s
+ elsif action != "original"
+ record.size.floor.to_s
+ else
+ nil
+ end
+ end
end
end
-
-ActionView::Base.send(:include, DynamicImage::Helper)