diff --git a/lib/paperclip/attachment.rb b/lib/paperclip/attachment.rb index eaef6b7..0e9ea94 100644 --- a/lib/paperclip/attachment.rb +++ b/lib/paperclip/attachment.rb @@ -48,7 +48,8 @@ module Paperclip attachment_class_cache[storage].new(name, instance, options) end - attr_reader :name, :instance, :styles, :default_style, :queued_for_write, :options + attr_reader :name, :instance, :options, :url_template, :path_template, + :styles, :default_style, :default_url, :validations, :whiny attr_accessor :post_processing @@ -61,8 +62,8 @@ module Paperclip options = Attachment.default_options.merge(options) - @url = options[:url] - @path = options[:path] + @url_template = options[:url] + @path_template = options[:path] @styles = StylesParser.new(options).styles @default_url = options[:default_url] @validations = options[:validations] @@ -70,14 +71,17 @@ module Paperclip @storage = options[:storage] @whiny = options[:whiny_thumbnails] || options[:whiny] @options = options - @queued_for_delete = [] - @queued_for_write = {} - @errors = {} - @validation_errors = nil - @dirty = false @post_processing = true - @processing_url = options[:processing_url] || @default_url + @processing_url = options[:processing_url] || default_url + end + + def queued_for_delete + @queued_for_delete ||= [] + end + + def queued_for_write + @queued_for_write ||= {} end # What gets called when you call instance.attachment = File. It clears @@ -104,7 +108,7 @@ module Paperclip end if image_content_type?(uploaded_file) && !valid_image_resolution?(uploaded_file) - @errors[:base] = :too_large_resolution + errors[:base] = :too_large_resolution return end return unless valid_assignment?(uploaded_file) @@ -114,10 +118,10 @@ module Paperclip return if uploaded_file.nil? - @queued_for_write[:original] = to_tempfile(uploaded_file) + queued_for_write[:original] = to_tempfile(uploaded_file) - file_name = if @options[:filename_sanitizer] - @options[:filename_sanitizer].call uploaded_file.original_filename, self + file_name = if options[:filename_sanitizer] + options[:filename_sanitizer].call uploaded_file.original_filename, self else sanitize_filename uploaded_file.original_filename end @@ -134,7 +138,7 @@ module Paperclip updater = :"#{name}_file_name_will_change!" instance.send updater if instance.respond_to? updater # Reset the file size if the original file was reprocessed. - instance_write(:file_size, @queued_for_write[:original].size.to_i) + instance_write(:file_size, queued_for_write[:original].size.to_i) ensure uploaded_file.close if close_uploaded_file validate @@ -160,17 +164,17 @@ module Paperclip # update time appended to the url def url style = default_style, include_updated_timestamp = true # for delayed_paperclip - return interpolate(@processing_url, style) if @instance.try("#{name}_processing?") - interpolate_url(@url, style, include_updated_timestamp) + return interpolate(processing_url, style) if instance.try("#{name}_processing?") + interpolate_url(url_template, style, include_updated_timestamp) end # Метод необходим в ассетах def filesystem_url style = default_style, include_updated_timestamp = true - interpolate_url(@url, style, include_updated_timestamp) + interpolate_url(url_template, style, include_updated_timestamp) end def interpolate_url(template, style, include_updated_timestamp) - url = original_filename.nil? ? interpolate(@default_url, style) : interpolate(template, style) + url = original_filename.nil? ? interpolate(default_url, style) : interpolate(template, style) include_updated_timestamp && updated_at ? [url, updated_at].compact.join(url.include?("?") ? "&" : "?") : url end @@ -180,7 +184,7 @@ module Paperclip # URL, and the :bucket option refers to the S3 bucket. def path style = default_style return if original_filename.nil? - interpolate(@path, style) + interpolate(path_template, style) end alias_method :filesystem_path, :path @@ -198,12 +202,12 @@ module Paperclip # Returns an array containing the errors on this attachment. def errors - @errors + @errors ||= {} end # Returns true if there are changes that need to be saved. def dirty? - @dirty + @dirty || false end # Saves the file, if there are no errors. If there are, it flushes them to @@ -225,8 +229,8 @@ module Paperclip # use #destroy. def clear queue_existing_for_delete - @errors = {} - @validation_errors = nil + errors.clear + @validated = false end # Destroys the attachment. Has the same effect as previously assigning @@ -246,7 +250,7 @@ module Paperclip # Returns the size of the file as originally assigned, and lives in the # _file_size attribute of the model. def size - instance_read(:file_size) || (@queued_for_write[:original] && @queued_for_write[:original].size) + instance_read(:file_size) || (queued_for_write[:original] && queued_for_write[:original].size) end # Returns the content_type of the file as originally assigned, and lives @@ -264,7 +268,7 @@ module Paperclip def sanitize_filename(file_name) file_name = file_name.strip - file_name.gsub!(@options[:restricted_characters], '_') if @options[:restricted_characters] + file_name.gsub!(options[:restricted_characters], '_') if options[:restricted_characters] # Укорачиваем слишком длинные имена файлов. if file_name.length > MAX_FILE_NAME_LENGTH @@ -308,14 +312,6 @@ module Paperclip instance.send(setter, value) if responds || attr.to_s == "file_name" end - def instance_update(attr, value) - setter = :"#{name}_#{attr}=" - responds = instance.respond_to?(setter) - self.instance_variable_set("@_#{setter.to_s.chop}", value) - instance.update_attribute(:"#{name}_#{attr}", value) if responds - end - - # Reads the attachment-specific attribute on the instance. See instance_write # for more details. def instance_read(attr) @@ -330,8 +326,8 @@ module Paperclip def ensure_required_accessors! #:nodoc: %w(file_name).each do |field| - unless @instance.respond_to?("#{name}_#{field}") && @instance.respond_to?("#{name}_#{field}=") - raise PaperclipError.new("#{@instance.class} model missing required attr_accessor for '#{name}_#{field}'") + unless instance.respond_to?("#{name}_#{field}") && instance.respond_to?("#{name}_#{field}=") + raise PaperclipError.new("#{instance.class} model missing required attr_accessor for '#{name}_#{field}'") end end end @@ -345,16 +341,13 @@ module Paperclip end def validate #:nodoc: - unless @validation_errors - @validation_errors = @validations.inject({}) do |errors, validation| - name, options = validation - errors[name] = send(:"validate_#{name}", options) if allow_validation?(options) - errors - end - @validation_errors.reject!{|k,v| v == nil } - @errors.merge!(@validation_errors) + return if @validated + validations.each do |validation| + name, options = validation + error = send(:"validate_#{name}", options) if allow_validation?(options) + errors[name] = error if error end - @validation_errors + @validated = true end def allow_validation? options #:nodoc: @@ -393,7 +386,7 @@ module Paperclip def post_process #:nodoc: return unless content_type.match(/image/) - return if @queued_for_write[:original].nil? + return if queued_for_write[:original].nil? instance.run_paperclip_callbacks(:post_process) do instance.run_paperclip_callbacks(:"#{name}_post_process") do @@ -406,12 +399,12 @@ module Paperclip styles.each do |name, args| begin raise RuntimeError.new("Style #{name} has no processors defined.") if args[:processors].blank? - @queued_for_write[name] = args[:processors].inject(@queued_for_write[:original]) do |file, processor| + queued_for_write[name] = args[:processors].inject(queued_for_write[:original]) do |file, processor| Paperclip.processor(processor).make(file, args, self) end rescue PaperclipError => e log("An error was received while processing: #{e.inspect}") - (@errors[:processing] ||= []) << e.message if @whiny + (errors[:processing] ||= []) << e.message if whiny end end end @@ -422,13 +415,12 @@ module Paperclip def queue_existing_for_delete #:nodoc: return unless file? - @queued_for_delete += [:original, *@styles.keys].uniq.map do |style| - filesystem_path(style) - end.compact + all_styles = [:original, *styles.keys] + queued_for_delete.concat(all_styles.uniq.map { |style| filesystem_path(style) }.compact) end def flush_errors #:nodoc: - @errors.each do |error, message| + errors.each do |error, message| [message].flatten.each {|m| instance.errors.add(name, m) } end end diff --git a/lib/paperclip/storage/delayeds3.rb b/lib/paperclip/storage/delayeds3.rb index 273ca67..4d6b834 100644 --- a/lib/paperclip/storage/delayeds3.rb +++ b/lib/paperclip/storage/delayeds3.rb @@ -72,19 +72,19 @@ module Paperclip def initialize(*) super - @s3_credentials = Delayeds3.parse_credentials(@options[:s3_credentials]) - @bucket = @options[:bucket] || @s3_credentials[:bucket] + @s3_credentials = Delayeds3.parse_credentials(options[:s3_credentials]) + @bucket = options[:bucket] || @s3_credentials[:bucket] - @fog_provider = @options[:fog_provider] - @fog_directory = @options[:fog_directory] - @fog_credentials = @options[:fog_credentials] + @fog_provider = options[:fog_provider] + @fog_directory = options[:fog_directory] + @fog_credentials = options[:fog_credentials] @queued_jobs = [] end def url(style = default_style, include_updated_timestamp = true) # for delayed_paperclip - return interpolate(@processing_url, style) if @instance.try("#{name}_processing?") + return interpolate(processing_url, style) if instance.try("#{name}_processing?") template = instance_read(:synced_to_s3) ? options[:s3_url] : options[:filesystem_url] interpolate_url(template, style, include_updated_timestamp) end @@ -139,7 +139,7 @@ module Paperclip end def to_file style = default_style - @queued_for_write[style] || (File.new(filesystem_path(style), 'rb') if exists?(style)) || download_file(style) + queued_for_write[style] || (File.new(filesystem_path(style), 'rb') if exists?(style)) || download_file(style) end def download_file(style = default_style) @@ -161,7 +161,7 @@ module Paperclip def filesystem_paths h = {} - [:original, *@styles.keys].uniq.map do |style| + [:original, *styles.keys].uniq.map do |style| path = filesystem_path(style) h[style] = path if File.exist?(path) end @@ -220,9 +220,9 @@ module Paperclip end def flush_writes #:nodoc: - return if @queued_for_write.empty? + return if queued_for_write.empty? - @queued_for_write.each do |style, file| + queued_for_write.each do |style, file| file.close FileUtils.mkdir_p(File.dirname(filesystem_path(style))) log("saving to filesystem #{filesystem_path(style)}") @@ -240,7 +240,7 @@ module Paperclip WriteToFogWorker.perform_async(instance.class.to_s, @name, instance.id) } end - @queued_for_write = {} + queued_for_write.clear end # Deletes a file and all parent directories if they are empty @@ -269,15 +269,15 @@ module Paperclip # если мы картинку заливали в облака, значит мы скорее всего ее уже удалили # и можно не нагружать хранилище проверками if instance_read(:synced_to_fog) && instance_read(:synced_to_s3) - @queued_for_delete = [] + queued_for_delete.clear return end - @queued_for_delete.each do |path| + queued_for_delete.each do |path| log("Deleting local file #{path}") delete_recursive(path) end - @queued_for_delete = [] + queued_for_delete.clear end def delete_local_files! diff --git a/lib/paperclip/storage/filesystem.rb b/lib/paperclip/storage/filesystem.rb index 39cb911..a99d6d5 100644 --- a/lib/paperclip/storage/filesystem.rb +++ b/lib/paperclip/storage/filesystem.rb @@ -27,12 +27,12 @@ module Paperclip # Returns representation of the data of the file assigned to the given # style, in the format most representative of the current storage. def to_file style = default_style - @queued_for_write[style] || (File.new(path(style), 'rb') if exists?(style)) + queued_for_write[style] || (File.new(path(style), 'rb') if exists?(style)) end alias_method :to_io, :to_file def flush_writes #:nodoc: - @queued_for_write.each do |style, file| + queued_for_write.each do |style, file| file.close filename = path(style) FileUtils.mkdir_p(File.dirname(filename)) @@ -40,11 +40,11 @@ module Paperclip FileUtils.mv(file.path, filename) FileUtils.chmod(0644, filename) end - @queued_for_write = {} + queued_for_write.clear end def flush_deletes #:nodoc: - @queued_for_delete.each do |path| + queued_for_delete.each do |path| begin log("deleting #{path}") FileUtils.rm(path) @@ -67,7 +67,7 @@ module Paperclip # Ignore it end end - @queued_for_delete = [] + queued_for_delete.clear end end end