file_storage 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ require 'rake_ext'
2
+
3
+ project(
4
+ name: "file_storage",
5
+ gem: true,
6
+ summary: "File storage for Models",
7
+
8
+ author: "Alexey Petrushin",
9
+ homepage: "http://github.com/alexeypetrushin/file_storage"
10
+ )
@@ -0,0 +1,11 @@
1
+ require 'carrierwave'
2
+
3
+ %w(
4
+ fixes
5
+ miscellaneous
6
+ mongo_model
7
+ ).each{|f| require "carrierwave_ext/#{f}"}
8
+
9
+ CarrierWave::Uploader::Base.class_eval do
10
+ def name; model.send("#{mounted_as}_filename") end
11
+ end
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ require 'rspec_ext'
2
+
3
+ require 'spec_helper/model_stub'
@@ -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: []