Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Provide the :tmp storage option for Paperclip

  • Loading branch information...
commit 9c5122ab373bbd39c3625fbe4ed1ef95d4f9858c 1 parent bf82aee
Olek Janiszewski authored
2  .rspec
View
@@ -0,0 +1,2 @@
+--color
+--format progress
5 CHANGELOG.md
View
@@ -0,0 +1,5 @@
+## Not released yet
+
+* Implement `Paperclip::Storage::Tmp.clear` which clears all
+ attachments from the filesystem (and from the "virtual" filesystem)
+* Provide a `:tmp` storage option for Paperclip attachments
2  Gemfile
View
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
# Specify your gem's dependencies in paperclip-storage-tmp.gemspec
gemspec
+
+gem 'paperclip', path: 'vendor/paperclip'
11 lib/paperclip-storage-tmp.rb
View
@@ -1,8 +1,3 @@
-require "paperclip-storage-tmp/version"
-
-module Paperclip
- module Storage
- module Tmp
- end
- end
-end
+require 'paperclip-storage-tmp/version'
+require 'paperclip'
+require 'paperclip/storage/tmp'
42 lib/paperclip/storage/tmp.rb
View
@@ -0,0 +1,42 @@
+module Paperclip
+ module Storage
+ module Tmp
+ def self.fs
+ @fs ||= {}
+ end
+
+ # Deletes the temporary files and releases references to them
+ def self.clear
+ fs.each_value {|f| f.unlink }
+ @fs = nil
+ end
+
+ def exists?(style_name = default_style)
+ Tmp.fs.key?(path(style_name))
+ end
+
+ def to_file(style_name = default_style)
+ @queued_for_write[style_name] || (File.new(Tmp.fs[path(style_name)], 'rb') if exists?(style_name))
+ end
+
+ def flush_writes
+ @queued_for_write.each do |style_name, file|
+ Tmp.fs[path(style_name)] = to_tempfile(file)
+ end
+
+ after_flush_writes
+ @queued_for_write = {}
+ end
+
+ def flush_deletes
+ @queued_for_delete.each do |path|
+ if file = Tmp.fs.delete(path)
+ file.unlink
+ end
+ end
+
+ @queued_for_delete = []
+ end
+ end
+ end
+end
1  paperclip-storage-tmp.gemspec
View
@@ -16,4 +16,5 @@ Gem::Specification.new do |gem|
gem.add_runtime_dependency 'paperclip', '~> 2.0'
gem.add_development_dependency 'rspec'
+ gem.add_development_dependency 'sqlite3'
end
BIN  spec/fixtures/hey_mom_its_me.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3  spec/fixtures/user.rb
View
@@ -0,0 +1,3 @@
+class User < ActiveRecord::Base
+ has_attached_file :avatar, storage: :tmp
+end
105 spec/lib/paperclip/storage/tmp_spec.rb
View
@@ -0,0 +1,105 @@
+require 'spec_helper'
+
+describe Paperclip::Storage::Tmp do
+ after do
+ Paperclip::Storage::Tmp.clear
+ end
+
+ let(:avatar_file) { File.new('spec/fixtures/hey_mom_its_me.png') }
+
+ [proc { user.avatar }, proc { user.reload.avatar }].each do |subject_proc|
+ describe 'assigning an attachment' do
+ let(:user) { User.create!(avatar: avatar_file) }
+ subject(&subject_proc)
+
+ it { should exist }
+ its(:content_type) { should eq('image/png') }
+ its(:original_filename) { should eq('hey_mom_its_me.png') }
+
+ its(:path) { should eq(Rails.root + "/public/system/avatars/1/original/hey_mom_its_me.png") }
+ its(:to_file) { should be_a(File) }
+
+ it 'is actually stored in /tmp' do
+ File.exists?(subject.path).should be_false
+ subject.to_file.path.should match(%r{^/tmp/})
+ end
+
+ it 'copies the assigned file' do
+ File.read(subject.to_file).should eq(File.read(avatar_file))
+ end
+
+ it 'stores the file in an imagemagick-friendly way' do
+ geometry = Paperclip::Geometry.from_file(subject.to_file)
+ geometry.width.should eq(256)
+ geometry.height.should eq(256)
+ end
+
+ it 'stores the file attributes in the model' do
+ user.avatar_file_name.should eq('hey_mom_its_me.png')
+ user.avatar_content_type.should eq('image/png')
+ user.avatar_file_size.should eq(File.size(avatar_file))
+ end
+
+ it 'can handle assignment from File' do
+ new_user = User.new(avatar: avatar_file)
+ new_user.avatar_file_name.should eq('hey_mom_its_me.png')
+ end
+
+ it 'can persist assignment from File' do
+ new_user = User.create!(avatar: avatar_file)
+ new_user.reload.avatar_file_name.should eq('hey_mom_its_me.png')
+ end
+
+ # :(
+ it 'cannot handle assignment from Paperclip::Attachment' do
+ new_user = User.new(avatar: subject)
+ new_user.avatar_file_name.should_not eq('hey_mom_its_me.png')
+ end
+ end
+
+ describe 'not assigning an attachment' do
+ let(:user) { User.create! }
+ subject(&subject_proc)
+
+ it { should_not exist }
+ its(:content_type) { should be_nil }
+ its(:original_filename) { should be_nil }
+ its(:path) { should be_nil }
+ its(:to_file) { should be_nil }
+ end
+ end
+
+ describe 'destroying an attachment' do
+ let(:user) { User.create!(avatar: avatar_file) }
+ subject do
+ @path_before_destroy = user.avatar.to_file.path
+ user.destroy
+
+ user.avatar
+ end
+
+ it { should_not exist }
+
+ it 'should be deleted from the filesystem' do
+ subject
+ File.exists?(@path_before_destroy).should be_false
+ end
+ end
+
+ describe 'clear' do
+ let(:user) { User.create!(avatar: avatar_file) }
+ subject { Paperclip::Storage::Tmp.clear }
+
+ it 'deletes files' do
+ path = user.avatar.to_file.path
+ subject
+ File.exists?(path).should be_false
+ end
+
+ it 'deletes the files from virtual fs' do
+ user.avatar.should exist
+ subject
+ user.avatar.should_not exist
+ end
+ end
+end
28 spec/meta_spec.rb
View
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe 'spec_helper' do
+ it 'successfully connects to an in-memory database' do
+ User.connection_config[:adapter].should eq('sqlite3')
+ User.connection_config[:database].should eq(':memory:')
+ User.create!
+ User.count.should eq(1)
+ end
+
+ it 'rolls back between examples' do
+ User.count.should eq(0)
+ end
+
+ it 'defines Rails.root' do
+ Rails.root.should eq(File.expand_path('../..', __FILE__))
+ end
+end
+
+describe User do
+ it 'is an active record' do
+ User.new.should be_an(ActiveRecord::Base)
+ end
+
+ it 'has an avatar' do
+ User.new.avatar.should be_a(Paperclip::Attachment)
+ end
+end
18 spec/spec_helper.rb
View
@@ -0,0 +1,18 @@
+require 'bundler'
+Bundler.setup
+
+require 'paperclip-storage-tmp'
+Dir[File.dirname(__FILE__) + '/support/*.rb'].each {|f| require f }
+
+RSpec.configure do |config|
+ config.treat_symbols_as_metadata_keys_with_true_values = true
+ config.run_all_when_everything_filtered = true
+ config.filter_run :focus
+
+ config.around do |example|
+ ActiveRecord::Base.transaction do
+ example.run
+ raise ActiveRecord::Rollback
+ end
+ end
+end
15 spec/support/active_record.rb
View
@@ -0,0 +1,15 @@
+require 'active_record'
+ActiveRecord::Base.send(:include, Paperclip::Glue)
+require 'fixtures/user'
+
+ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
+
+ActiveRecord::Schema.define do
+ create_table :users do |t|
+ t.string :avatar_file_name
+ t.string :avatar_content_type
+ t.integer :avatar_file_size
+ t.datetime :created_at
+ t.datetime :updated_at
+ end
+end
3  spec/support/fake_rails.rb
View
@@ -0,0 +1,3 @@
+module Rails
+ def self.root; File.expand_path('../../..', __FILE__); end
+end
1  spec/support/paperclip.rb
View
@@ -0,0 +1 @@
+Paperclip.logger = Logger.new(STDOUT).tap {|l| l.level = Logger::WARN }
0  vendor/.gitkeep
View
No changes.
Please sign in to comment.
Something went wrong with that request. Please try again.