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
# 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
# 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
For the given methods - versions should call the main uploader 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
# File lib/cloudinary/carrier_wave/process.rb, line 124 def all_processors (self.is_main_uploader? ? [] : all_versions_processors) + self.class.processors end
# 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
Rename preloaded uploads if public_id
was overridden
# File lib/cloudinary/carrier_wave.rb, line 141 def auto_rename_preloaded? true end
# 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
# 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
# File lib/cloudinary/carrier_wave.rb, line 116 def cache_versions!(new_file=nil) # Do nothing end
Let Cloudinary
download remote URLs directly
# File lib/cloudinary/carrier_wave.rb, line 136 def cloudinary_should_handle_remote? true end
# File lib/cloudinary/carrier_wave.rb, line 195 def default_format "png" end
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
# 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
# File lib/cloudinary/carrier_wave/process.rb, line 128 def eager @eager ||= self.all_processors.any?{|processor| processor[0] == :eager} end
# 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
# 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
# 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
# File lib/cloudinary/carrier_wave.rb, line 19 def is_main_uploader? self.class.version_names.blank? end
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
# File lib/cloudinary/carrier_wave.rb, line 120 def process!(new_file=nil) # Do nothing end
# File lib/cloudinary/carrier_wave.rb, line 112 def recreate_versions! # Do nothing end
# 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
# 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
# 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
# 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
# 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
# File lib/cloudinary/carrier_wave.rb, line 125 def sanitize(filename) return nil if filename.nil? filename.gsub(SANITIZE_REGEXP, '_') end
# 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
# File lib/cloudinary/carrier_wave.rb, line 199 def storage_type @file.respond_to?(:storage_type) ? @file.storage_type : self.class.storage_type end
# 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
# File lib/cloudinary/carrier_wave.rb, line 23 def stored_version @stored_version end
# 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
# 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 format that includes resource type and storage type.
# File lib/cloudinary/carrier_wave.rb, line 146 def use_extended_identifier? true end