mirror of
https://github.com/kemko/paperclip.git
synced 2026-01-01 16:05:40 +03:00
Merge pull request #91 from insales/fix_styles_tmp
Delete intermediary tempfiles
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ gemfiles/*.lock
|
|||||||
gemfiles/.bundle/
|
gemfiles/.bundle/
|
||||||
tmp/
|
tmp/
|
||||||
.rubocop-*
|
.rubocop-*
|
||||||
|
/coverage/
|
||||||
|
|||||||
7
.pryrc
Normal file
7
.pryrc
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Alieases for debugger.
|
||||||
|
if defined?(PryByebug) || defined?(PryDebugger)
|
||||||
|
Pry.commands.alias_command 'c', 'continue'
|
||||||
|
Pry.commands.alias_command 's', 'step'
|
||||||
|
Pry.commands.alias_command 'n', 'next'
|
||||||
|
Pry.commands.alias_command 'f', 'finish'
|
||||||
|
end
|
||||||
1
Gemfile
1
Gemfile
@@ -15,6 +15,7 @@ gem 'rails'
|
|||||||
gem 'sidekiq'
|
gem 'sidekiq'
|
||||||
|
|
||||||
gem 'test-unit'
|
gem 'test-unit'
|
||||||
|
gem 'simplecov', require: false
|
||||||
gem 'mocha'
|
gem 'mocha'
|
||||||
gem 'thoughtbot-shoulda', '>= 2.9.0'
|
gem 'thoughtbot-shoulda', '>= 2.9.0'
|
||||||
|
|
||||||
|
|||||||
42
Rakefile
42
Rakefile
@@ -3,7 +3,6 @@ require 'rake/testtask'
|
|||||||
require 'rdoc/task'
|
require 'rdoc/task'
|
||||||
|
|
||||||
$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
|
$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
|
||||||
require 'paperclip'
|
|
||||||
|
|
||||||
import 'lib/tasks/paperclip_tasks.rake'
|
import 'lib/tasks/paperclip_tasks.rake'
|
||||||
|
|
||||||
@@ -19,7 +18,7 @@ Rake::TestTask.new(:test) do |t|
|
|||||||
end
|
end
|
||||||
|
|
||||||
desc 'Start an IRB session with all necessary files required.'
|
desc 'Start an IRB session with all necessary files required.'
|
||||||
task :shell do
|
task :shell => :load_paperclip do
|
||||||
chdir File.dirname(__FILE__)
|
chdir File.dirname(__FILE__)
|
||||||
exec 'irb -I lib/ -I lib/paperclip -r rubygems -r active_record -r tempfile -r init'
|
exec 'irb -I lib/ -I lib/paperclip -r rubygems -r active_record -r tempfile -r init'
|
||||||
end
|
end
|
||||||
@@ -62,23 +61,28 @@ exclude_file_globs = ["test/s3.yml",
|
|||||||
"test/pkg/*",
|
"test/pkg/*",
|
||||||
"test/tmp",
|
"test/tmp",
|
||||||
"test/tmp/*"]
|
"test/tmp/*"]
|
||||||
spec = Gem::Specification.new do |s|
|
|
||||||
s.name = "paperclip"
|
def spec
|
||||||
s.version = Paperclip::VERSION
|
# TODO: require 'paperclip/version'
|
||||||
s.author = "Jon Yurek"
|
require 'paperclip'
|
||||||
s.email = "jyurek@thoughtbot.com"
|
Gem::Specification.new do |s|
|
||||||
s.homepage = "http://www.thoughtbot.com/projects/paperclip"
|
s.name = "paperclip"
|
||||||
s.platform = Gem::Platform::RUBY
|
s.version = Paperclip::VERSION
|
||||||
s.summary = "File attachments as attributes for ActiveRecord"
|
s.author = "Jon Yurek"
|
||||||
s.files = FileList[include_file_globs].to_a - FileList[exclude_file_globs].to_a
|
s.email = "jyurek@thoughtbot.com"
|
||||||
s.require_path = "lib"
|
s.homepage = "http://www.thoughtbot.com/projects/paperclip"
|
||||||
s.test_files = FileList["test/**/test_*.rb"].to_a
|
s.platform = Gem::Platform::RUBY
|
||||||
s.rubyforge_project = "paperclip"
|
s.summary = "File attachments as attributes for ActiveRecord"
|
||||||
s.extra_rdoc_files = FileList["README*"].to_a
|
s.files = FileList[include_file_globs].to_a - FileList[exclude_file_globs].to_a
|
||||||
s.rdoc_options << '--line-numbers' << '--inline-source'
|
s.require_path = "lib"
|
||||||
s.requirements << "ImageMagick"
|
s.test_files = FileList["test/**/test_*.rb"].to_a
|
||||||
s.add_development_dependency 'thoughtbot-shoulda'
|
s.rubyforge_project = "paperclip"
|
||||||
s.add_development_dependency 'mocha'
|
s.extra_rdoc_files = FileList["README*"].to_a
|
||||||
|
s.rdoc_options << '--line-numbers' << '--inline-source'
|
||||||
|
s.requirements << "ImageMagick"
|
||||||
|
s.add_development_dependency 'thoughtbot-shoulda'
|
||||||
|
s.add_development_dependency 'mocha'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Print a list of the files to be put into the gem"
|
desc "Print a list of the files to be put into the gem"
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ module Paperclip
|
|||||||
# thumbnails forcefully, by reobtaining the original file and going through
|
# thumbnails forcefully, by reobtaining the original file and going through
|
||||||
# the post-process again.
|
# the post-process again.
|
||||||
def reprocess!
|
def reprocess!
|
||||||
new_original = Tempfile.new("paperclip-reprocess-#{instance.id}-")
|
new_original = Tempfile.new("paperclip-reprocess-#{instance.class.table_name}-#{instance.id}-")
|
||||||
new_original.binmode
|
new_original.binmode
|
||||||
old_original = to_file(:original)
|
old_original = to_file(:original)
|
||||||
new_original.write( old_original.read )
|
new_original.write( old_original.read )
|
||||||
@@ -431,7 +431,11 @@ module Paperclip
|
|||||||
begin
|
begin
|
||||||
raise RuntimeError.new("Style #{name} has no processors defined.") if args[:processors].blank?
|
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)
|
Paperclip.processor(processor).make(file, args, self).tap do |new_file|
|
||||||
|
# closing intermediary tempfiles
|
||||||
|
file.close! if new_file != file && file.is_a?(Tempfile) &&
|
||||||
|
(name == :original || !queued_for_write.value?(file))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
rescue PaperclipError => e
|
rescue PaperclipError => e
|
||||||
log("An error was received while processing: #{e.inspect}")
|
log("An error was received while processing: #{e.inspect}")
|
||||||
|
|||||||
@@ -3,12 +3,10 @@ require 'open3'
|
|||||||
module Paperclip
|
module Paperclip
|
||||||
class Optimizer < Processor
|
class Optimizer < Processor
|
||||||
def make
|
def make
|
||||||
optimized_file_path = optimize(@file)
|
optimized_file = optimize(@file)
|
||||||
if optimized_file_path && File.exist?(optimized_file_path)
|
return @file unless optimized_file && optimized_file.size > 0 # rubocop:disable Style/ZeroLengthPredicate
|
||||||
return File.open(optimized_file_path)
|
|
||||||
else
|
optimized_file
|
||||||
return @file
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def real_content_type
|
def real_content_type
|
||||||
@@ -18,9 +16,9 @@ module Paperclip
|
|||||||
def optimize(_file)
|
def optimize(_file)
|
||||||
# TODO: use the arg?
|
# TODO: use the arg?
|
||||||
src = @file.path
|
src = @file.path
|
||||||
dst = "#{src}-#{SecureRandom.hex}"
|
dst_file = Tempfile.new(["#{File.basename(src)}-optim", File.extname(src)])
|
||||||
src_shell = src.shellescape
|
src_shell = src.shellescape
|
||||||
dst_shell = dst.shellescape
|
dst_shell = dst_file.path.shellescape
|
||||||
cmd = case real_content_type
|
cmd = case real_content_type
|
||||||
when 'image/jpeg', 'image/jpg', 'image/pjpeg'
|
when 'image/jpeg', 'image/jpg', 'image/pjpeg'
|
||||||
"cp #{src_shell} #{dst_shell} && jpegoptim --all-progressive -q --strip-com --strip-exif --strip-iptc -- #{dst_shell}"
|
"cp #{src_shell} #{dst_shell} && jpegoptim --all-progressive -q --strip-com --strip-exif --strip-iptc -- #{dst_shell}"
|
||||||
@@ -32,7 +30,11 @@ module Paperclip
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
run_and_verify!(cmd)
|
run_and_verify!(cmd)
|
||||||
dst
|
dst_file
|
||||||
|
rescue StandardError => e
|
||||||
|
dst_file.close!
|
||||||
|
Paperclip.log("Error: cannot optimize: #{e}")
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -5,8 +5,12 @@ module Paperclip
|
|||||||
# если по каким-то причинам не сформировался файл
|
# если по каким-то причинам не сформировался файл
|
||||||
# для прыдущего размера не кидаем ексепшен и
|
# для прыдущего размера не кидаем ексепшен и
|
||||||
# генерим файл из оригинального
|
# генерим файл из оригинального
|
||||||
f = attachment.to_file(options[:thumbnail] || :original) rescue file
|
source_style = options[:thumbnail] || :original
|
||||||
super f, options, attachment
|
# TODO: вообще queued_for_write[source_style] место в NoCacheS3#to_file
|
||||||
|
f = attachment&.queued_for_write&.dig(source_style)&.tap(&:rewind)
|
||||||
|
# TODO: и надо сносить файл если все же была загрузка
|
||||||
|
f ||= attachment.to_file(source_style) rescue file # rubocop:disable Style/RescueModifier
|
||||||
|
super(f, options, attachment)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -142,9 +142,8 @@ module Paperclip
|
|||||||
(self.class.store_ids - [self.class.main_store_id]).each { |store_id| enqueue_sync_job(store_id) }
|
(self.class.store_ids - [self.class.main_store_id]).each { |store_id| enqueue_sync_job(store_id) }
|
||||||
end
|
end
|
||||||
# HACK: Iostream пишет в tempfile, и он нигде не закрывается. Будем закрывать хотя бы тут
|
# HACK: Iostream пишет в tempfile, и он нигде не закрывается. Будем закрывать хотя бы тут
|
||||||
if queued_for_write[:original].is_a?(Tempfile)
|
queued_for_write.each_value do |file|
|
||||||
queued_for_write[:original].close
|
file.is_a?(Tempfile) && file.close!
|
||||||
queued_for_write[:original].unlink
|
|
||||||
end
|
end
|
||||||
queued_for_write.clear
|
queued_for_write.clear
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ module Paperclip
|
|||||||
def make
|
def make
|
||||||
src = @file
|
src = @file
|
||||||
ext = @format.present? ? ".#{@format}" : nil
|
ext = @format.present? ? ".#{@format}" : nil
|
||||||
dst = Tempfile.new([@basename, ext])
|
dst = Tempfile.new(["#{@basename}-thumb-", ext])
|
||||||
dst.binmode
|
dst.binmode
|
||||||
|
|
||||||
command = <<-end_command
|
command = <<-end_command
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ require 'test_helper'
|
|||||||
require 'sidekiq'
|
require 'sidekiq'
|
||||||
require 'sidekiq/testing'
|
require 'sidekiq/testing'
|
||||||
require 'aws-sdk-s3'
|
require 'aws-sdk-s3'
|
||||||
|
require 'base64'
|
||||||
|
|
||||||
require 'delayed_paperclip'
|
require 'delayed_paperclip'
|
||||||
DelayedPaperclip::Railtie.insert
|
DelayedPaperclip::Railtie.insert
|
||||||
@@ -29,6 +30,12 @@ class NoCacheS3Test < Test::Unit::TestCase
|
|||||||
stores: {
|
stores: {
|
||||||
store_1: { access_key_id: '123', secret_access_key: '123', region: 'r', bucket: 'buck' },
|
store_1: { access_key_id: '123', secret_access_key: '123', region: 'r', bucket: 'buck' },
|
||||||
store_2: { access_key_id: '456', secret_access_key: '456', region: 'r', bucket: 'buck' }
|
store_2: { access_key_id: '456', secret_access_key: '456', region: 'r', bucket: 'buck' }
|
||||||
|
},
|
||||||
|
styles: {
|
||||||
|
original: { geometry: '4x4>', processors: %i[thumbnail optimizer] },
|
||||||
|
medium: '3x3',
|
||||||
|
small: { geometry: '2x2', processors: [:recursive_thumbnail], thumbnail: :medium },
|
||||||
|
micro: { geometry: '1x1', processors: [:recursive_thumbnail], thumbnail: :small }
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
modify_table(:dummies) do |table|
|
modify_table(:dummies) do |table|
|
||||||
@@ -36,12 +43,14 @@ class NoCacheS3Test < Test::Unit::TestCase
|
|||||||
table.boolean :avatar_synced_to_store_2, null: false, default: false
|
table.boolean :avatar_synced_to_store_2, null: false, default: false
|
||||||
end
|
end
|
||||||
@instance = Dummy.create
|
@instance = Dummy.create
|
||||||
@store1_stub = mock
|
@store1_stub = mock("store1")
|
||||||
@store2_stub = mock
|
@store2_stub = mock("store2")
|
||||||
@store1_stub.stubs(:url).returns('http://store.local')
|
@store1_stub.stubs(:url).returns('http://store.local')
|
||||||
@store2_stub.stubs(:url).returns('http://store.local')
|
@store2_stub.stubs(:url).returns('http://store.local')
|
||||||
@instance.avatar.class.stubs(:stores).returns({ store_1: @store1_stub, store_2: @store2_stub })
|
@instance.avatar.class.stubs(:stores).returns({ store_1: @store1_stub, store_2: @store2_stub })
|
||||||
Dummy::AvatarAttachment.any_instance.stubs(:to_file).returns(stub_file('text.txt', 'qwe'))
|
Dummy::AvatarAttachment.any_instance.stubs(:to_file).returns(
|
||||||
|
stub_file('pixel.gif', Base64.decode64('R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw'))
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
teardown { TEST_ROOT.rmtree if TEST_ROOT.exist? }
|
teardown { TEST_ROOT.rmtree if TEST_ROOT.exist? }
|
||||||
@@ -83,6 +92,22 @@ class NoCacheS3Test < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "reprocess" do
|
||||||
|
setup do
|
||||||
|
Sidekiq::Testing.fake!
|
||||||
|
@instance.update_columns avatar_file_name: 'foo.gif', avatar_content_type: 'image/gif'
|
||||||
|
end
|
||||||
|
|
||||||
|
should "delete tmp files" do
|
||||||
|
@store1_stub.expects(:put_object).times(1 + (@instance.avatar.options[:styles].keys - [:original]).size)
|
||||||
|
# Paperclip.expects(:log).with { puts "Log: #{_1}"; true }.at_least(3)
|
||||||
|
existing_files = Dir.children(Dir.tmpdir)
|
||||||
|
@instance.avatar.reprocess!
|
||||||
|
leftover_files = (Dir.children(Dir.tmpdir) - existing_files).sort
|
||||||
|
assert_empty(leftover_files)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'generating presigned_url' do
|
context 'generating presigned_url' do
|
||||||
setup do
|
setup do
|
||||||
Dummy::AvatarAttachment.any_instance.stubs(:storage_url).returns('http://домен.pф/ключ?param1=параметр')
|
Dummy::AvatarAttachment.any_instance.stubs(:storage_url).returns('http://домен.pф/ключ?param1=параметр')
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
|
require 'bundler/setup'
|
||||||
|
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
require 'shoulda'
|
require 'shoulda'
|
||||||
require 'mocha/test_unit'
|
require 'mocha/test_unit'
|
||||||
@@ -13,6 +15,24 @@ require 'active_record'
|
|||||||
require 'active_support'
|
require 'active_support'
|
||||||
require 'rails'
|
require 'rails'
|
||||||
|
|
||||||
|
if ENV['COVERAGE']
|
||||||
|
require 'simplecov'
|
||||||
|
|
||||||
|
SimpleCov.external_at_exit = true
|
||||||
|
Test::Unit.at_exit do
|
||||||
|
SimpleCov.at_exit_behavior
|
||||||
|
end
|
||||||
|
SimpleCov.command_name 'test:units'
|
||||||
|
SimpleCov.start do
|
||||||
|
load_profile "test_frameworks"
|
||||||
|
|
||||||
|
add_group "Storage", "lib/paperclip/storage/"
|
||||||
|
add_group "Libraries", "lib/"
|
||||||
|
|
||||||
|
track_files "{lib}/**/*.rb"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
ROOT = File.expand_path('../', __dir__)
|
ROOT = File.expand_path('../', __dir__)
|
||||||
|
|
||||||
ENV['RAILS_ENV'] = 'test'
|
ENV['RAILS_ENV'] = 'test'
|
||||||
@@ -20,9 +40,10 @@ class TestRailsApp < Rails::Application; end
|
|||||||
Rails.application.config.root = "#{ROOT}/tmp/rails"
|
Rails.application.config.root = "#{ROOT}/tmp/rails"
|
||||||
|
|
||||||
$LOAD_PATH << File.join(ROOT, 'lib')
|
$LOAD_PATH << File.join(ROOT, 'lib')
|
||||||
$LOAD_PATH << File.join(ROOT, 'lib', 'paperclip')
|
$LOAD_PATH << File.join(ROOT, 'lib/paperclip') # ??
|
||||||
|
|
||||||
require File.join(ROOT, 'lib', 'paperclip.rb')
|
require 'paperclip'
|
||||||
|
# require File.join(ROOT, 'lib/paperclip.rb')
|
||||||
|
|
||||||
require 'shoulda_macros/paperclip'
|
require 'shoulda_macros/paperclip'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user