module Cloudinary::CarrierWave

Copyright Cloudinary Support for store in CarrierWave files that were preloaded to cloudinary (e.g., by javascript) Field value must be in the format: “image/upload/v<version>/<public_id>.<format>#<signature>” Where signature is the cloudinary API signature on the public_id and version.

Constants

PRELOADED_CLOUDINARY_PATH
SANITIZE_REGEXP
SHORT_STORED_CLOUDINARY_PATH
STORED_CLOUDINARY_PATH

Public Class Methods

createRawOrPreloaded(file) click to toggle source
# File lib/cloudinary/carrier_wave/preloaded.rb, line 88
def self.createRawOrPreloaded(file)
  return file if file.is_a?(Cloudinary::CarrierWave::StoredFile)
  return PreloadedCloudinaryFile.new(file) if file.is_a?(String) && file.match(PRELOADED_CLOUDINARY_PATH)
  nil
end
included(base) click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 10
def self.included(base)
  base.storage Cloudinary::CarrierWave::Storage
  base.cache_storage = :file if base.cache_storage.blank?
  base.extend ClassMethods
  base.class_attribute :metadata
  base.class_attribute :storage_type, instance_reader: false
  override_in_versions(base, :blank?, :full_public_id, :my_public_id, :all_versions_processors, :stored_version)
end
override_in_versions(base, *methods) click to toggle source

For the given methods - versions should call the main uploader method

Calls superclass method
# File lib/cloudinary/carrier_wave.rb, line 208
def self.override_in_versions(base, *methods)
  methods.each do
    |method|
    base.send :define_method, method do
      return super() if self.version_name.blank?
      uploader = self.model.send(self.mounted_as)
      uploader.send(method)
    end
  end
end

Public Instance Methods

all_processors() click to toggle source
# File lib/cloudinary/carrier_wave/process.rb, line 124
def all_processors
  (self.is_main_uploader? ? [] : all_versions_processors) + self.class.processors
end
all_versions_processors() click to toggle source
# File lib/cloudinary/carrier_wave/process.rb, line 118
def all_versions_processors
  all_versions = self.class.instance_variable_get('@all_versions')

  all_versions ? all_versions.processors : []
end
auto_rename_preloaded?() click to toggle source

Rename preloaded uploads if public_id was overridden

# File lib/cloudinary/carrier_wave.rb, line 141
def auto_rename_preloaded?
  true
end
cache!(new_file) click to toggle source
Calls superclass method
# File lib/cloudinary/carrier_wave/preloaded.rb, line 10
def cache!(new_file)
  file = Cloudinary::CarrierWave::createRawOrPreloaded(new_file)
  if file
    @file = file
    @stored_version = @file.version
    @public_id = @stored_public_id = @file.public_id
    self.original_filename = sanitize(@file.original_filename)
    @cache_id = "unused" # must not be blank
  else
    super
    @public_id = nil # allow overriding public_id
  end
end
cache_name() click to toggle source
Calls superclass method
# File lib/cloudinary/carrier_wave/preloaded.rb, line 38
def cache_name
  return (@file.is_a?(PreloadedCloudinaryFile) || @file.is_a?(StoredFile)) ? @file.to_s : super
end
cache_versions!(new_file=nil) click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 116
def cache_versions!(new_file=nil)
  # Do nothing
end
cloudinary_should_handle_remote?() click to toggle source

Let Cloudinary download remote URLs directly

# File lib/cloudinary/carrier_wave.rb, line 136
def cloudinary_should_handle_remote?
  true
end
default_format() click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 195
def default_format
  "png"
end
default_public_id() click to toggle source

default public_id to use if no uploaded file. Override with public_id of an uploaded image if you want a default image.

# File lib/cloudinary/carrier_wave.rb, line 73
def default_public_id
  nil
end
delete_remote?() click to toggle source

Should removed files be removed from Cloudinary as well. Can be overridden.

# File lib/cloudinary/carrier_wave.rb, line 131
def delete_remote?
  true
end
download!(uri, *args) click to toggle source
Calls superclass method
# File lib/cloudinary/carrier_wave/remote.rb, line 2
def download!(uri, *args)
  return super unless self.cloudinary_should_handle_remote?
  if respond_to?(:process_uri)
    uri = process_uri(uri)
  else # Backward compatibility with old CarrierWave
    remote_url_unsafe_chars = /([^a-zA-Z0-9_.\-\/:?&=]+)/ # In addition allow query string characters: "?","&" and "="
    uri = URI.parse(Cloudinary::Utils.smart_escape(Cloudinary::Utils.smart_unescape(uri), remote_url_unsafe_chars))
  end
  return if uri.to_s.blank?
  self.original_filename = @cache_id = @filename = File.basename(uri.path).gsub(/[^a-zA-Z0-9\.\-\+_]/, '')
  @file = RemoteFile.new(uri, @filename)
end
eager() click to toggle source
# File lib/cloudinary/carrier_wave/process.rb, line 128
def eager
  @eager ||= self.all_processors.any?{|processor| processor[0] == :eager}
end
filename() click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 67
def filename
  return nil if self.blank?
  return [self.full_public_id, self.format].reject(&:blank?).join(".")
end
format() click to toggle source
# File lib/cloudinary/carrier_wave/process.rb, line 153
def format
  format = Cloudinary::PreloadedFile.split_format(original_filename || "").last
  return format || "" if resource_type == "raw"
  format = requested_format || format || default_format

  format = format.to_s.downcase
  Cloudinary::FORMAT_ALIASES[format] || format
end
full_public_id() click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 61
def full_public_id
  return nil if self.blank?
  return self.my_public_id if self.stored_version.blank?
  return "v#{self.stored_version}/#{self.my_public_id}"
end
is_main_uploader?() click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 19
def is_main_uploader?
  self.class.version_names.blank?
end
my_public_id() click to toggle source

If the user overrode public_id, that should be used, even if it’s different from current public_id in the database. Otherwise, try to use public_id from the database. Otherwise, generate a new random public_id

# File lib/cloudinary/carrier_wave.rb, line 85
def my_public_id
  @public_id ||= self.public_id
  @public_id ||= @stored_public_id
  @public_id ||= Cloudinary::Utils.random_public_id
end
process!(new_file=nil) click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 120
def process!(new_file=nil)
  # Do nothing
end
public_id() click to toggle source

public_id to use for uploaded file. Can be overridden by caller. Random public_id will be used otherwise.

# File lib/cloudinary/carrier_wave.rb, line 78
def public_id
  nil
end
recreate_versions!() click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 112
def recreate_versions!
  # Do nothing
end
rename(to_public_id = nil, overwrite=false) click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 91
def rename(to_public_id = nil, overwrite=false)
  public_id_overwrite = self.public_id
  to_public_id ||= public_id_overwrite
  if public_id_overwrite && to_public_id != public_id_overwrite
    raise CloudinaryException, "The public_id method was overridden and returns #{public_id_overwrite} - can't rename to #{to_public_id}"
  elsif to_public_id.nil?
    raise CloudinaryException, "No to_public_id given"
  end

  from_public_id = @stored_public_id || self.my_public_id
  return if from_public_id == to_public_id

  @public_id = @stored_public_id = to_public_id
  if self.resource_type == 'raw'
    from_public_id = [from_public_id, self.format].join(".")
    to_public_id = [to_public_id, self.format].join(".")
  end
  Cloudinary::Uploader.rename(from_public_id, to_public_id, :type=>self.storage_type, :resource_type=>self.resource_type, :overwrite=>overwrite)
  storage.store_cloudinary_identifier(@stored_version, [@public_id, self.format].join("."))
end
requested_format() click to toggle source
# File lib/cloudinary/carrier_wave/process.rb, line 138
def requested_format
  format_processor = self.all_processors.find{|processor| processor[0] == :convert}
  if format_processor
    # Explicit format is given
    format = Array(format_processor[1]).first
  elsif self.transformation.include?(:format)
    format = self.transformation[:format]
  elsif self.version_name.present?
    # No local format. The reset should be handled by main uploader
    uploader = self.model.send(self.mounted_as)
    format = uploader.format
  end
  format
end
resource_type() click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 203
def resource_type
  @file.respond_to?(:resource_type) ? @file.resource_type : Cloudinary::Utils.resource_type_for_format(requested_format || original_filename || default_format)
end
retrieve_from_cache!(new_file) click to toggle source
Calls superclass method
# File lib/cloudinary/carrier_wave/preloaded.rb, line 24
def retrieve_from_cache!(new_file)
  file = Cloudinary::CarrierWave::createRawOrPreloaded(new_file)
  if file
    @file = file
    @stored_version = @file.version
    @public_id = @stored_public_id = @file.public_id
    self.original_filename = sanitize(@file.original_filename)
    @cache_id = "unused" # must not be blank
  else
    super
    @public_id = nil # allow overriding public_id
  end
end
retrieve_from_store!(identifier) click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 27
def retrieve_from_store!(identifier)
  # Workaround cloudinary-mongoid hack of setting column to _old_ before saving it.
  mongoid_blank = defined?(Mongoid::Extensions::Object) && self.is_a?(Mongoid::Extensions::Object) && identifier == "_old_"
  if identifier.blank? || mongoid_blank
    @file = @stored_version = @stored_public_id = nil
    self.original_filename = nil
  else
    @file = CloudinaryFile.new(identifier, self)
    @public_id = @stored_public_id = @file.public_id
    @stored_version = @file.version
    self.original_filename = sanitize(@file.filename)
  end
end
sanitize(filename) click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 125
def sanitize(filename)
  return nil if filename.nil?
  filename.gsub(SANITIZE_REGEXP, '_')
end
set_or_yell(hash, attr, value) click to toggle source
# File lib/cloudinary/carrier_wave/process.rb, line 53
def set_or_yell(hash, attr, value)
  raise CloudinaryException, "conflicting transformation on #{attr} #{value}!=#{hash[attr]}" if hash[attr] && hash[attr] != value
  hash[attr] = value
end
storage_type() click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 199
def storage_type
  @file.respond_to?(:storage_type) ? @file.storage_type : self.class.storage_type
end
store!(new_file=nil) click to toggle source
Calls superclass method
# File lib/cloudinary/carrier_wave/process.rb, line 162
def store!(new_file=nil)
  super

  column = model.send(:_mounter, mounted_as).send(:serialization_column)
  original_value = model.read_attribute(column)
  identifiers = original_value.is_a?(Array) ? original_value : [original_value]

  identifiers.each do |identifier|
    retrieve_from_store!(identifier) unless identifier.nil?
  end
end
stored_version() click to toggle source
# File lib/cloudinary/carrier_wave.rb, line 23
def stored_version
  @stored_version
end
tags() click to toggle source
# File lib/cloudinary/carrier_wave/process.rb, line 132
def tags
  @tags ||= self.all_processors.select{|processor| processor[0] == :tags}.map(&:second).first
  raise CloudinaryException, "tags cannot be used in versions." if @tags.present? && self.version_name.present?
  @tags
end
transformation() click to toggle source
# File lib/cloudinary/carrier_wave/process.rb, line 58
def transformation
  return @transformation if @transformation
  @transformation = {}
  self.all_processors.each do |name, args, condition|

    if(condition)
      if condition.respond_to?(:call)
        next unless condition.call(self, :args => args)
      else
        next unless self.send(condition)
      end
    end

    case name
    when :convert # Do nothing. This is handled by format
    when :resize_to_limit
      set_or_yell(@transformation, :width, args[0])
      set_or_yell(@transformation, :height, args[1])
      set_or_yell(@transformation, :crop, :limit)
    when :resize_to_fit
      set_or_yell(@transformation, :width, args[0])
      set_or_yell(@transformation, :height, args[1])
      set_or_yell(@transformation, :crop, :fit)
    when :resize_to_fill
      set_or_yell(@transformation, :width, args[0])
      set_or_yell(@transformation, :height, args[1])
      set_or_yell(@transformation, :gravity, args[2].to_s.downcase)
      set_or_yell(@transformation, :crop, :fill)
    when :resize_and_pad
      set_or_yell(@transformation, :width, args[0])
      set_or_yell(@transformation, :height, args[1])
      set_or_yell(@transformation, :background, args[2].to_s.downcase)
      set_or_yell(@transformation, :gravity, args[3].to_s.downcase)
      set_or_yell(@transformation, :crop, :pad)
    when :scale
      set_or_yell(@transformation, :width, args[0])
      set_or_yell(@transformation, :height, args[1])
      set_or_yell(@transformation, :crop, :scale)
    when :crop
      set_or_yell(@transformation, :width, args[0])
      set_or_yell(@transformation, :height, args[1])
      set_or_yell(@transformation, :gravity, args[2].to_s.downcase)
      set_or_yell(@transformation, :crop, :crop)
    when :cloudinary_transformation
      args.each do
        |attr, value|
        set_or_yell(@transformation, attr, value)
      end
    else
      if args.blank?
        Array(send(name)).each do
          |attr, value|
          set_or_yell(@transformation, attr, value)
        end
      end
    end
  end
  @transformation
end
url(*args) click to toggle source
Calls superclass method
# File lib/cloudinary/carrier_wave.rb, line 41
def url(*args)
  if args.first && !args.first.is_a?(Hash)
    super
  else
    options = args.extract_options!
    if self.blank?
      url = self.default_url
      return url if !url.blank?
      public_id = self.default_public_id
      return nil if public_id.nil?
    else
      public_id = self.my_public_id
      options[:version] ||= self.stored_version
    end
    options = self.transformation.merge(options) if self.version_name.present?

    Cloudinary::Utils.cloudinary_url(public_id, {:format=>self.format, :resource_type=>self.resource_type, :type=>self.storage_type}.merge(options))
  end
end
use_extended_identifier?() click to toggle source

Use extended identifier format that includes resource type and storage type.

# File lib/cloudinary/carrier_wave.rb, line 146
def use_extended_identifier?
  true
end