class CarrierWave::Mounter

:nodoc:
we don’t pollute the model with a lot of methods.
this is an internal class, used by CarrierWave::Mount so that

def self.build(record, column)

def self.build(record, column)
  if record.class.uploader_options[column][:multiple]
    Multiple.new(record, column)
  else
    Single.new(record, column)
  end
end

def blank?

def blank?
  uploaders.none?(&:present?)
end

def blank_uploader

def blank_uploader
  uploader_class.new(record, column)
end

def cache(new_files)

def cache(new_files)
  return if !new_files.is_a?(Array) && new_files.blank?
  old_uploaders = uploaders
  @uploaders = new_files.map do |new_file|
    handle_error do
      if new_file.is_a?(String)
        if (uploader = old_uploaders.detect { |old_uploader| old_uploader.identifier == new_file })
          uploader.staged = true
          uploader
        else
          begin
            uploader = blank_uploader
            uploader.retrieve_from_cache!(new_file)
            uploader
          rescue CarrierWave::InvalidParameter
            nil
          end
        end
      else
        uploader = blank_uploader
        uploader.cache!(new_file)
        uploader
      end
    end
  end.reject(&:blank?)
  @removed_uploaders += (old_uploaders - @uploaders)
  write_temporary_identifier
end

def cache_names

def cache_names
  uploaders.map(&:cache_name).compact
end

def cache_names=(cache_names)

def cache_names=(cache_names)
  cache_names = cache_names.reject(&:blank?)
  return if cache_names.blank?
  clear_unstaged
  cache_names.each do |cache_name|
    uploader = blank_uploader
    uploader.retrieve_from_cache!(cache_name)
    @uploaders << uploader
  rescue CarrierWave::InvalidParameter
    # ignore
  end
  write_temporary_identifier
end

def clear!

def clear!
  @removed_uploaders += uploaders
  @remove = nil
  @uploaders = []
end

def clear_unstaged

def clear_unstaged
  uploaders # Ensure that uploaders are initialized based on the current value
  staged, unstaged = @uploaders.partition(&:staged)
  @uploaders = staged
  @removed_uploaders += unstaged
end

def handle_error

def handle_error
  yield
rescue CarrierWave::DownloadError => e
  @download_errors << e
  raise e unless option(:ignore_download_errors)
rescue CarrierWave::ProcessingError => e
  @processing_errors << e
  raise e unless option(:ignore_processing_errors)
rescue CarrierWave::IntegrityError => e
  @integrity_errors << e
  raise e unless option(:ignore_integrity_errors)
end

def identifiers

def identifiers
  uploaders.map(&:identifier)
end

def initialize(record, column)

def initialize(record, column)
  @record = record
  @column = column
  @options = record.class.uploader_options[column]
  @download_errors = []
  @processing_errors = []
  @integrity_errors = []
  @removed_uploaders = []
  @added_uploaders = []
end

def option(name)

def option(name)
  self.uploader_options ||= {}
  self.uploader_options[name] ||= record.class.uploader_option(column, name)
end

def read_identifiers

def read_identifiers
  [record.read_uploader(serialization_column)].flatten.reject(&:blank?)
end

def remote_urls=(urls)

def remote_urls=(urls)
  if urls.nil?
    urls = []
  else
    urls = Array.wrap(urls).reject(&:blank?)
    return if urls.blank?
  end
  @download_errors.clear
  @remote_urls = urls
  clear_unstaged
  @remote_urls.zip(remote_request_headers || []) do |url, header|
    handle_error do
      uploader = blank_uploader
      uploader.download!(url, header || {})
      @uploaders << uploader
    end
  end
  write_temporary_identifier
end

def remove!

def remove!
  uploaders.each(&:remove!)
  clear!
end

def remove=(value)

def remove=(value)
  uploaders # Ensure that uploaders are initialized based on the current value
  @remove = value
  write_temporary_identifier
end

def remove?

def remove?
  remove.present? && (remove.to_s !~ /\A0|false$\z/)
end

def remove_added

def remove_added
  current_paths = (@removed_uploaders + uploaders.select(&:staged)).map(&:path)
  @added_uploaders
    .reject {|uploader| current_paths.include?(uploader.path) }
    .each { |uploader| uploader.remove! }
  reset_changes!
end

def remove_previous

def remove_previous
  current_paths = uploaders.map(&:path)
  @removed_uploaders
    .reject {|uploader| current_paths.include?(uploader.path) }
    .each { |uploader| uploader.remove! if uploader.remove_previously_stored_files_after_update }
  reset_changes!
end

def reset_changes!

def reset_changes!
  @removed_uploaders = []
  @added_uploaders = []
end

def serialization_column

def serialization_column
  option(:mount_on) || column
end

def store!

def store!
  uploaders.each(&:store!)
end

def temporary_identifiers

def temporary_identifiers
  if remove?
    []
  else
    uploaders.map { |uploader| uploader.temporary_identifier }
  end
end

def uploader_class

def uploader_class
  record.class.uploaders[column]
end

def uploaders

def uploaders
  @uploaders ||= read_identifiers.map do |identifier|
    uploader = blank_uploader
    uploader.retrieve_from_store!(identifier)
    uploader
  end
end

def urls(*args)

def urls(*args)
  uploaders.map { |u| u.url(*args) }
end

def write_identifier

def write_identifier
  return if record.frozen?
  clear! if remove?
  additions, remains = uploaders.partition(&:cached?)
  existing_identifiers = (@removed_uploaders + remains).map(&:identifier)
  additions.each do |uploader|
    uploader.deduplicate(existing_identifiers)
    existing_identifiers << uploader.identifier
  end
  @added_uploaders += additions
  record.write_uploader(serialization_column, identifier)
end

def write_temporary_identifier

def write_temporary_identifier
  return if record.frozen?
  record.write_uploader(serialization_column, temporary_identifier)
end