file_storage 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +10 -0
- data/lib/carrierwave_ext.rb +11 -0
- data/lib/carrierwave_ext/fixes.rb +12 -0
- data/lib/carrierwave_ext/miscellaneous.rb +26 -0
- data/lib/carrierwave_ext/mongo_model.rb +40 -0
- data/lib/carrierwave_ext/spec.rb +23 -0
- data/readme.md +1 -0
- data/spec/file_storage_spec.rb +145 -0
- data/spec/file_storage_spec/invalid.txt +0 -0
- data/spec/file_storage_spec/ship.jpg +0 -0
- data/spec/file_storage_spec/ship2.jpg +0 -0
- data/spec/file_storage_spec//321/204/320/260/320/270/314/206/320/273 /321/201 /320/277/321/200/320/276/320/261/320/265/320/273/320/260/320/274/320/270.txt" +1 -0
- data/spec/model_integration_spec.rb +89 -0
- data/spec/model_integration_spec/invalid.txt +0 -0
- data/spec/model_integration_spec/ship.jpg +0 -0
- data/spec/model_integration_spec/ship2.jpg +0 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/spec_helper/model_stub.rb +43 -0
- metadata +62 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
CarrierWave::SanitizedFile.class_eval do
|
|
2
|
+
def sanitize_regexp
|
|
3
|
+
/[^[:word:]\.\-\+\s_]/i
|
|
4
|
+
end
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
CarrierWave::Uploader::Cache.class_eval do
|
|
8
|
+
def original_filename=(filename)
|
|
9
|
+
raise CarrierWave::InvalidParameter, "invalid filename" unless filename =~ /\A[[:word:]\.\-\+\s_]+\z/i
|
|
10
|
+
@original_filename = filename
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Changing filename format from <version>_<filename_with_extension> to <name>.<version>.<extension>
|
|
3
|
+
#
|
|
4
|
+
CarrierWave::Uploader::Versions.class_eval do
|
|
5
|
+
def full_filename(for_file)
|
|
6
|
+
name = super
|
|
7
|
+
if version_name
|
|
8
|
+
ext = File.extname name
|
|
9
|
+
base = File.basename name, ext
|
|
10
|
+
"#{base}.#{version_name}#{ext}"
|
|
11
|
+
else
|
|
12
|
+
name
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def full_original_filename
|
|
17
|
+
name = super
|
|
18
|
+
if version_name
|
|
19
|
+
ext = File.extname name
|
|
20
|
+
base = File.basename name, ext
|
|
21
|
+
"#{base}.#{version_name}#{ext}"
|
|
22
|
+
else
|
|
23
|
+
name
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'mongo_db/model'
|
|
4
|
+
|
|
5
|
+
module CarrierWave
|
|
6
|
+
module MongoModel
|
|
7
|
+
def read_uploader name
|
|
8
|
+
send name
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def write_uploader name, value
|
|
12
|
+
send :"#{name}=", value
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module ClassMethods
|
|
16
|
+
include CarrierWave::Mount
|
|
17
|
+
##
|
|
18
|
+
# See +CarrierWave::Mount#mount_uploader+ for documentation
|
|
19
|
+
#
|
|
20
|
+
def mount_uploader(column, uploader, options={}, &block)
|
|
21
|
+
fname_attribute = :"#{column}_filename"
|
|
22
|
+
attr_accessor fname_attribute
|
|
23
|
+
|
|
24
|
+
options[:mount_on] ||= fname_attribute
|
|
25
|
+
|
|
26
|
+
super
|
|
27
|
+
|
|
28
|
+
# include CarrierWave::Validations::ActiveModel
|
|
29
|
+
# validates_integrity_of column if uploader_option(column.to_sym, :validate_integrity)
|
|
30
|
+
# validates_processing_of column if uploader_option(column.to_sym, :validate_processing)
|
|
31
|
+
|
|
32
|
+
after_save "store_#{column}!".to_sym
|
|
33
|
+
before_save "write_#{column}_identifier".to_sym
|
|
34
|
+
after_destroy "remove_#{column}!".to_sym
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
Mongo::Model.inherit CarrierWave::MongoModel
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module CarrierWaveExtSpecHelper
|
|
2
|
+
TEST_PATH, TEST_CACHE_PATH = '/tmp/spec_fs', '/tmp/spec_fs_cache'
|
|
3
|
+
|
|
4
|
+
def with_files
|
|
5
|
+
before do
|
|
6
|
+
CarrierWave.configure do |config|
|
|
7
|
+
config.storage = :file
|
|
8
|
+
config.enable_processing = false
|
|
9
|
+
|
|
10
|
+
config.cache_dir = TEST_CACHE_PATH
|
|
11
|
+
config.root = TEST_PATH
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
before do
|
|
16
|
+
[TEST_PATH, TEST_CACHE_PATH].each{|p| FileUtils.rm_r(p) if File.exist?(p)}
|
|
17
|
+
end
|
|
18
|
+
before do
|
|
19
|
+
[TEST_PATH, TEST_CACHE_PATH].each{|p| FileUtils.rm_r(p) if File.exist?(p)}
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
rspec.extend CarrierWaveExtSpecHelper
|
data/readme.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
File storage for Models
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'mini_magick'
|
|
5
|
+
|
|
6
|
+
describe "File Storage" do
|
|
7
|
+
before :all do
|
|
8
|
+
class ImageFile
|
|
9
|
+
include FileStorage
|
|
10
|
+
|
|
11
|
+
process do
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
version :icon do
|
|
15
|
+
process do
|
|
16
|
+
end
|
|
17
|
+
# process convert: :png
|
|
18
|
+
# process resize_to_fit: [50, 50]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def path_prefix
|
|
22
|
+
self.class.path_prefix
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def url_prefix
|
|
26
|
+
'/'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def validate
|
|
30
|
+
errors << 'invalid name' if original and original.name =~ /invalid/
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class << self
|
|
34
|
+
attr_accessor :path_prefix
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
after(:all){remove_constants :ImageFile}
|
|
39
|
+
|
|
40
|
+
before do
|
|
41
|
+
ImageFile.path_prefix = "#{spec_dir}/storage"
|
|
42
|
+
@file = "#{spec_dir}/ship.jpg".to_file
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "CRUD" do
|
|
46
|
+
# blank
|
|
47
|
+
image = ImageFile.new
|
|
48
|
+
image.file.should be_nil
|
|
49
|
+
image.url.should == nil
|
|
50
|
+
image.icon.file.should be_nil
|
|
51
|
+
image.icon.url.should == nil
|
|
52
|
+
|
|
53
|
+
# preserving
|
|
54
|
+
image.original = @file
|
|
55
|
+
image.original.name.should == 'ship.jpg'
|
|
56
|
+
image.original.path.should == "#{spec_dir}/ship.jpg"
|
|
57
|
+
|
|
58
|
+
image.file.should be_nil
|
|
59
|
+
image.url.should == nil
|
|
60
|
+
image.icon.file.should be_nil
|
|
61
|
+
image.icon.url.should == nil
|
|
62
|
+
|
|
63
|
+
# writing
|
|
64
|
+
image.save
|
|
65
|
+
image.file.name.should == 'ship.jpg'
|
|
66
|
+
image.file.path.should == "#{spec_dir}/storage/ship.jpg"
|
|
67
|
+
image.file.exist?.should be_true
|
|
68
|
+
image.url.should == '/ship.jpg'
|
|
69
|
+
|
|
70
|
+
image.icon.file.name.should == 'ship.jpg'
|
|
71
|
+
image.icon.file.path.should == "#{spec_dir}/storage/ship.icon.jpg"
|
|
72
|
+
image.icon.file.exist?.should be_true
|
|
73
|
+
image.icon.url.should == '/ship.icon.jpg'
|
|
74
|
+
|
|
75
|
+
# reading
|
|
76
|
+
image = ImageFile.new
|
|
77
|
+
image.read 'ship.jpg'
|
|
78
|
+
|
|
79
|
+
image.file.name.should == 'ship.jpg'
|
|
80
|
+
image.file.path.should == "#{spec_dir}/storage/ship.jpg"
|
|
81
|
+
image.file.exist?.should be_true
|
|
82
|
+
image.url.should == '/ship.jpg'
|
|
83
|
+
|
|
84
|
+
image.icon.file.name.should == 'ship.jpg'
|
|
85
|
+
image.icon.file.path.should == "#{spec_dir}/storage/ship.icon.jpg"
|
|
86
|
+
image.icon.file.exist?.should be_true
|
|
87
|
+
image.icon.url.should == '/ship.icon.jpg'
|
|
88
|
+
|
|
89
|
+
# updating
|
|
90
|
+
image.original = @file
|
|
91
|
+
image.original.name.should == 'ship2.jpg'
|
|
92
|
+
image.original.path.should == "#{spec_dir}/ship2.jpg"
|
|
93
|
+
|
|
94
|
+
image.save
|
|
95
|
+
|
|
96
|
+
"#{spec_dir}/storage/ship.jpg".to_file.exist?.should be_false
|
|
97
|
+
"#{spec_dir}/storage/ship.icon.jpg".to_file.exist?.should be_false
|
|
98
|
+
|
|
99
|
+
image.file.name.should == 'ship2.jpg'
|
|
100
|
+
image.file.path.should == "#{spec_dir}/storage/ship2.jpg"
|
|
101
|
+
image.file.exist?.should be_true
|
|
102
|
+
image.url.should == '/ship2.jpg'
|
|
103
|
+
|
|
104
|
+
image.icon.file.name.should == 'ship2.jpg'
|
|
105
|
+
image.icon.file.path.should == "#{spec_dir}/storage/ship2.icon.jpg"
|
|
106
|
+
image.icon.file.exist?.should be_true
|
|
107
|
+
image.icon.url.should == '/ship.icon2.jpg'
|
|
108
|
+
|
|
109
|
+
# destroying
|
|
110
|
+
image = ImageFile.new
|
|
111
|
+
image.read 'ship.jpg'
|
|
112
|
+
image.destroy
|
|
113
|
+
"#{spec_dir}/storage/ship2.jpg".to_file.exist?.should be_false
|
|
114
|
+
"#{spec_dir}/storage/ship2.icon.jpg".to_file.exist?.should be_false
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "should preserve spaces and unicode characters in filename" do
|
|
118
|
+
file = "#{spec_dir}/файл с пробелами.txt".to_file
|
|
119
|
+
|
|
120
|
+
image = ImageFile.new
|
|
121
|
+
image.save file
|
|
122
|
+
image.url.should =~ /\/файл с пробелами\.txt/
|
|
123
|
+
image.file.path.should =~ /\/файл с пробелами\.txt/
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'should raise error if file not exists' do
|
|
127
|
+
image = ImageFile.new
|
|
128
|
+
image.original = "#{spec_dir}/non existing file.jpg".to_file
|
|
129
|
+
image.validate
|
|
130
|
+
image.errors.first.should =~ /not exist/
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it 'should validate and not save invalid files' do
|
|
134
|
+
image = ImageFile.new
|
|
135
|
+
image.original = "#{spec_dir}/ship.jpg".to_file
|
|
136
|
+
image.validate
|
|
137
|
+
image.errors.should == []
|
|
138
|
+
|
|
139
|
+
image.original == "#{spec_dir}/invalid.jpg".to_file
|
|
140
|
+
image.validate
|
|
141
|
+
image.errors.should == ['invalid filename']
|
|
142
|
+
|
|
143
|
+
-> {image.save}.should raise_error(/invalid/)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe 'Model Integration' do
|
|
4
|
+
before :all do
|
|
5
|
+
class ImageFile
|
|
6
|
+
inherit FileStorage
|
|
7
|
+
|
|
8
|
+
def validate
|
|
9
|
+
errors << 'invalid name' if original and (original.name =~ /invalid/)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class TheModel < ModelStub
|
|
14
|
+
inherit FileStorage::Helper
|
|
15
|
+
|
|
16
|
+
mount_file :image, ImageFile
|
|
17
|
+
|
|
18
|
+
alias_method :attribute_get, :instance_variable_get
|
|
19
|
+
alias_method :attribute_set, :instance_variable_set
|
|
20
|
+
|
|
21
|
+
before_validate.push -> {|_self|
|
|
22
|
+
self.image.validate
|
|
23
|
+
self.errors[:image] = image.errors unless image.errors.empty?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
after_save.push -> {|_self| self.image.save}
|
|
27
|
+
|
|
28
|
+
after_destroy.push -> {|_self| self.image.destroy}
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
after(:all){remove_constants :ImageFile, :TheModel}
|
|
33
|
+
|
|
34
|
+
it 'CRUD' do
|
|
35
|
+
# read
|
|
36
|
+
model = TheModel.new
|
|
37
|
+
model.image.class.should == ImageStorage
|
|
38
|
+
model.image.url.should be_nil
|
|
39
|
+
model.image.file.should be_nil
|
|
40
|
+
|
|
41
|
+
# preserving
|
|
42
|
+
file = spec_dir.to_dir / 'ship.jpg'
|
|
43
|
+
model.image = file
|
|
44
|
+
model.image.original.path.should == "#{spec_dir}/ship.jpg"
|
|
45
|
+
model.instance_variable_get(:@image).should == 'ship.jpg'
|
|
46
|
+
model.image.url.should be_nil
|
|
47
|
+
model.image.file.path.should be_nil
|
|
48
|
+
|
|
49
|
+
# saving
|
|
50
|
+
model.save.should be_true
|
|
51
|
+
model.instance_variable_get(:@image).should == 'ship.jpg'
|
|
52
|
+
model.image.url.should == '/ship.jpg'
|
|
53
|
+
model.image.file.path.should == "#{spec_dir}/ship.jpg"
|
|
54
|
+
"#{spec_dir}/ship.jpg".to_file.exist?.should be_true
|
|
55
|
+
|
|
56
|
+
# reading
|
|
57
|
+
model = TheModel.new
|
|
58
|
+
model.instance_variable_set(:@image, 'ship.jpg')
|
|
59
|
+
model.image.url.should == '/ship.jpg'
|
|
60
|
+
model.image.file.path.should == "#{spec_dir}/ship.jpg"
|
|
61
|
+
|
|
62
|
+
# updating
|
|
63
|
+
file2 = spec_dir.to_dir / 'ship2.jpg'
|
|
64
|
+
model.image = file2
|
|
65
|
+
model.instance_variable_get(:@image).should == 'ship2.jpg'
|
|
66
|
+
model.image.original.path.should == "#{spec_dir}/ship2.jpg"
|
|
67
|
+
model.image.url.should == '/ship.jpg'
|
|
68
|
+
model.image.file.path.should == "#{spec_dir}/ship.jpg"
|
|
69
|
+
|
|
70
|
+
model.save.should be_true
|
|
71
|
+
model.instance_variable_get(:@image).should == 'ship2.jpg'
|
|
72
|
+
model.image.url.should == '/ship2.jpg'
|
|
73
|
+
model.image.file.path.should == "#{spec_dir}/ship2.jpg"
|
|
74
|
+
"#{spec_dir}/ship.jpg".to_file.exist?.should be_false
|
|
75
|
+
"#{spec_dir}/ship2.jpg".to_file.exist?.should be_true
|
|
76
|
+
|
|
77
|
+
# destroying
|
|
78
|
+
model.destroy.should be_false
|
|
79
|
+
"#{spec_dir}/ship2.jpg".to_file.exist?.should be_false
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "should be able to submit errors and interrupt model saving" do
|
|
83
|
+
file = spec_dir.to_dir / 'invalid.txt'
|
|
84
|
+
model.image = file
|
|
85
|
+
model.image.should_not_receive(:save)
|
|
86
|
+
model.save.should be_false
|
|
87
|
+
model.errors[:image].should == ['invalid name']
|
|
88
|
+
end
|
|
89
|
+
end
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
class ModelStub
|
|
2
|
+
def errors
|
|
3
|
+
@errors ||= {}
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def save
|
|
7
|
+
before_validate.each{|m| send m}
|
|
8
|
+
|
|
9
|
+
if errors.empty?
|
|
10
|
+
# save
|
|
11
|
+
after_save.each{|m| send m}
|
|
12
|
+
true
|
|
13
|
+
else
|
|
14
|
+
false
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def destroy
|
|
19
|
+
before_validate.each{|b| instance_eval &b}
|
|
20
|
+
|
|
21
|
+
if errors.empty?
|
|
22
|
+
# save
|
|
23
|
+
after_destroy.each{|b| instance_eval &b}
|
|
24
|
+
true
|
|
25
|
+
else
|
|
26
|
+
false
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class << self
|
|
31
|
+
def before_validate
|
|
32
|
+
@before_validate ||= []
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def before_save
|
|
36
|
+
@before_save ||= []
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def before_destroy
|
|
40
|
+
@before_destroy ||= []
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: file_storage
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Alexey Petrushin
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2011-08-27 00:00:00.000000000Z
|
|
13
|
+
dependencies: []
|
|
14
|
+
description:
|
|
15
|
+
email:
|
|
16
|
+
executables: []
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- Rakefile
|
|
21
|
+
- readme.md
|
|
22
|
+
- lib/carrierwave_ext/fixes.rb
|
|
23
|
+
- lib/carrierwave_ext/miscellaneous.rb
|
|
24
|
+
- lib/carrierwave_ext/mongo_model.rb
|
|
25
|
+
- lib/carrierwave_ext/spec.rb
|
|
26
|
+
- lib/carrierwave_ext.rb
|
|
27
|
+
- spec/file_storage_spec/invalid.txt
|
|
28
|
+
- spec/file_storage_spec/ship.jpg
|
|
29
|
+
- spec/file_storage_spec/ship2.jpg
|
|
30
|
+
- spec/file_storage_spec/файл с пробелами.txt
|
|
31
|
+
- spec/file_storage_spec.rb
|
|
32
|
+
- spec/model_integration_spec/invalid.txt
|
|
33
|
+
- spec/model_integration_spec/ship.jpg
|
|
34
|
+
- spec/model_integration_spec/ship2.jpg
|
|
35
|
+
- spec/model_integration_spec.rb
|
|
36
|
+
- spec/spec_helper/model_stub.rb
|
|
37
|
+
- spec/spec_helper.rb
|
|
38
|
+
homepage: http://github.com/alexeypetrushin/file_storage
|
|
39
|
+
licenses: []
|
|
40
|
+
post_install_message:
|
|
41
|
+
rdoc_options: []
|
|
42
|
+
require_paths:
|
|
43
|
+
- lib
|
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
45
|
+
none: false
|
|
46
|
+
requirements:
|
|
47
|
+
- - ! '>='
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '0'
|
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
51
|
+
none: false
|
|
52
|
+
requirements:
|
|
53
|
+
- - ! '>='
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '0'
|
|
56
|
+
requirements: []
|
|
57
|
+
rubyforge_project:
|
|
58
|
+
rubygems_version: 1.8.6
|
|
59
|
+
signing_key:
|
|
60
|
+
specification_version: 3
|
|
61
|
+
summary: File storage for Models
|
|
62
|
+
test_files: []
|