require "paperclip/attachment_registry" module Paperclip module Task def self.obtain_class class_name = ENV["CLASS"] || ENV["class"] raise "Must specify CLASS" unless class_name class_name end def self.obtain_attachments(klass) klass = Paperclip.class_for(klass.to_s) name = ENV["ATTACHMENT"] || ENV["attachment"] attachment_names = Paperclip::AttachmentRegistry.names_for(klass) raise "Class #{klass.name} has no attachments specified" if attachment_names.empty? if name.present? && attachment_names.map(&:to_s).include?(name.to_s) [name] else attachment_names end end def self.log_error(error) $stderr.puts error end end end namespace :paperclip do desc "Refreshes both metadata and thumbnails." task refresh: ["paperclip:refresh:metadata", "paperclip:refresh:thumbnails"] namespace :refresh do desc "Regenerates thumbnails for a given CLASS (and optional ATTACHMENT and STYLES splitted by comma)." task thumbnails: :environment do klass = Paperclip::Task.obtain_class names = Paperclip::Task.obtain_attachments(klass) styles = (ENV["STYLES"] || ENV["styles"] || "").split(",").map(&:to_sym) names.each do |name| Paperclip.each_instance_with_attachment(klass, name) do |instance| attachment = instance.send(name) begin attachment.reprocess!(*styles) rescue StandardError => e Paperclip::Task.log_error("exception while processing #{klass} ID #{instance.id}:") Paperclip::Task.log_error(" " + e.message + "\n") end unless instance.errors.blank? Paperclip::Task.log_error("errors while processing #{klass} ID #{instance.id}:") Paperclip::Task.log_error(" " + instance.errors.full_messages.join("\n ") + "\n") end end end end desc "Regenerates content_type/size metadata for a given CLASS (and optional ATTACHMENT)." task metadata: :environment do klass = Paperclip::Task.obtain_class names = Paperclip::Task.obtain_attachments(klass) names.each do |name| Paperclip.each_instance_with_attachment(klass, name) do |instance| attachment = instance.send(name) if file = Paperclip.io_adapters.for(attachment, attachment.options[:adapter_options]) instance.send("#{name}_file_name=", instance.send("#{name}_file_name").strip) instance.send("#{name}_content_type=", file.content_type.to_s.strip) instance.send("#{name}_file_size=", file.size) if instance.respond_to?("#{name}_file_size") instance.save(validate: false) else true end end end end desc "Regenerates missing thumbnail styles for all classes using Paperclip." task missing_styles: :environment do Rails.application.eager_load! Paperclip.missing_attachments_styles.each do |klass, attachment_definitions| attachment_definitions.each do |attachment_name, missing_styles| puts "Regenerating #{klass} -> #{attachment_name} -> #{missing_styles.inspect}" ENV["CLASS"] = klass.to_s ENV["ATTACHMENT"] = attachment_name.to_s ENV["STYLES"] = missing_styles.join(",") Rake::Task["paperclip:refresh:thumbnails"].execute end end Paperclip.save_current_attachments_styles! end desc "Regenerates fingerprints for a given CLASS (and optional ATTACHMENT). Useful when changing digest." task fingerprints: :environment do klass = Paperclip::Task.obtain_class names = Paperclip::Task.obtain_attachments(klass) names.each do |name| Paperclip.each_instance_with_attachment(klass, name) do |instance| attachment = instance.send(name) attachment.assign(attachment) instance.save(validate: false) end end end end desc "Cleans out invalid attachments. Useful after you've added new validations." task clean: :environment do klass = Paperclip::Task.obtain_class names = Paperclip::Task.obtain_attachments(klass) names.each do |name| Paperclip.each_instance_with_attachment(klass, name) do |instance| unless instance.valid? attributes = %w(file_size file_name content_type).map { |suffix| "#{name}_#{suffix}".to_sym } if attributes.any? { |attribute| instance.errors[attribute].present? } instance.send("#{name}=", nil) instance.save(validate: false) end end end end end desc "find missing attachments. Useful to know which attachments are broken" task find_broken_attachments: :environment do klass = Paperclip::Task.obtain_class names = Paperclip::Task.obtain_attachments(klass) names.each do |name| Paperclip.each_instance_with_attachment(klass, name) do |instance| attachment = instance.send(name) if attachment.exists? print "." else Paperclip::Task.log_error("#{instance.class}##{attachment.name}, #{instance.id}, #{attachment.url}") end end end end end