file_validators 2.1.0 → 2.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 451e981eb130a49dc6c51834bd7ed4dd30652c9a
4
- data.tar.gz: e6b28941ccf9ced999b0e201ad17738efb8bc767
3
+ metadata.gz: 75fbf34dcce7be5b3770f09d4068c00f50f2cd9d
4
+ data.tar.gz: e81f181e641308492a13b1ef3ed5034724d2a7f6
5
5
  SHA512:
6
- metadata.gz: 8c40fa1dae6faf187cc4d3ba77db40691b9bfe58fe9fa99bc88b9fc36477b49ef06bd360ffa8a8af4e2d6f4d56421259b9d9623ab3732a06883b8e64c3f57eb4
7
- data.tar.gz: 4c6aed01f6c15c42c3f917dcdbbbb4c28907ed662a16f823e33d7416005122e159f2504d4991f5fd4b7b20405b332566a1d52137164f224ce5c1504df1c45407
6
+ metadata.gz: abb281ff04de1964a07f19d2ee5fa5ccc51f63827b0ae7bb2628c3ddc36379d16ad48e9aa037d5e16ed18a6ab5d0690b0cc866a263c48ce9a754006c53204d9f
7
+ data.tar.gz: 01417d071f54021f5c8ad73b6a9eb5d35c7b49b29c450037dd2b3b40cbaa13fb9250bf9cfc66931385caab5e2bd934b51987329a736a87645ce6cfa7063bee6c
data/.gitignore CHANGED
@@ -11,3 +11,5 @@ gemfiles/*.lock
11
11
  coverage/
12
12
  /.idea
13
13
  .ruby-version
14
+ .agignore
15
+ tags
data/.travis.yml CHANGED
@@ -7,12 +7,11 @@ rvm:
7
7
  - jruby-9.0.4.0
8
8
 
9
9
  gemfile:
10
+ - gemfiles/activemodel_5.0.gemfile
10
11
  - gemfiles/activemodel_4.2.gemfile
11
12
  - gemfiles/activemodel_4.1.gemfile
12
13
  - gemfiles/activemodel_4.0.gemfile
13
14
  - gemfiles/activemodel_3.2.gemfile
14
- - gemfiles/activemodel_3.1.gemfile
15
- - gemfiles/activemodel_3.0.gemfile
16
15
 
17
16
  matrix:
18
17
  allow_failures:
data/Appraisals CHANGED
@@ -1,17 +1,9 @@
1
- appraise 'activemodel-3.0' do
2
- gem 'activemodel', '3.0.20'
3
- end
4
-
5
- appraise 'activemodel-3.1' do
6
- gem 'activemodel', '3.1.12'
7
- end
8
-
9
1
  appraise 'activemodel-3.2' do
10
- gem 'activemodel', '3.2.18'
2
+ gem 'activemodel', '3.2.22.5'
11
3
  end
12
4
 
13
5
  appraise 'activemodel-4.0' do
14
- gem 'activemodel', '4.0.10'
6
+ gem 'activemodel', '4.0.13'
15
7
  end
16
8
 
17
9
  appraise 'activemodel-4.1' do
@@ -19,5 +11,9 @@ appraise 'activemodel-4.1' do
19
11
  end
20
12
 
21
13
  appraise 'activemodel-4.2' do
22
- gem 'activemodel', '4.2.3'
14
+ gem 'activemodel', '4.2.7.1'
15
+ end
16
+
17
+ appraise 'activemodel-5.0' do
18
+ gem 'activemodel', '5.0.1'
23
19
  end
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # 2.2.0-beta.1
2
+
3
+ * [#17](https://github.com/musaffa/file_validators/pull/17) Now Supports multiple file uploads
4
+ * As activemodel 3.0 and 3.1 doesn't support `added?` method on the Errors class, the support for both of them have been deprecated in this release.
5
+
6
+ # 2.1.0
7
+
8
+ * Use autoload for lazy loading of libraries.
9
+ * Media type spoof valiation is moved to content type detector.
10
+ * `spoofed_file_media_type` message isn't needed anymore.
11
+ * Logger info and warning is added.
data/README.md CHANGED
@@ -12,8 +12,11 @@ Any module that uses ActiveModel, for example ActiveRecord, can use these file v
12
12
 
13
13
  ## Support
14
14
 
15
- * ActiveModel versions: 3 and 4.
16
- * Rails versions: 3 and 4.
15
+ * ActiveModel versions: 3.2, 4 and 5.
16
+ * Rails versions: 3.2, 4 and 5.
17
+
18
+ As of version `2.2`, activemodel 3.0 and 3.1 will no longer be supported.
19
+ For activemodel 3.0 and 3.1, please use file_validators version `<= 2.1`.
17
20
 
18
21
  It has been tested to work with Carrierwave, Paperclip, Dragonfly, Refile etc file uploading solutions.
19
22
  Validations works both before and after uploads.
@@ -253,8 +256,8 @@ $ rake test:unit
253
256
  $ rake test:integration
254
257
 
255
258
  # test different active model versions
256
- $ appraisal install
257
- $ appraisal rake
259
+ $ bundle exec appraisal install
260
+ $ bundle exec appraisal rake
258
261
  ```
259
262
 
260
263
  ## Problems
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
17
17
  s.test_files = s.files.grep(%r{^spec/})
18
18
  s.require_paths = ['lib']
19
19
 
20
- s.add_dependency 'activemodel', '>= 3.0'
20
+ s.add_dependency 'activemodel', '>= 3.2'
21
21
  s.add_dependency 'mime-types', '>= 1.0'
22
22
 
23
23
  s.add_development_dependency 'cocaine', '~> 0.5.4'
@@ -3,6 +3,6 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
- gem "activemodel", "3.2.18"
6
+ gem "activemodel", "3.2.22.5"
7
7
 
8
8
  gemspec :path => "../"
@@ -3,6 +3,6 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
- gem "activemodel", "4.0.10"
6
+ gem "activemodel", "4.0.13"
7
7
 
8
8
  gemspec :path => "../"
@@ -3,6 +3,6 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
- gem "activemodel", "4.2.3"
6
+ gem "activemodel", "4.2.7.1"
7
7
 
8
8
  gemspec :path => "../"
@@ -3,6 +3,6 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
- gem "activemodel", "3.0.20"
6
+ gem "activemodel", "5.0.1"
7
7
 
8
8
  gemspec :path => "../"
@@ -22,20 +22,23 @@ module FileValidators
22
22
 
23
23
  # content type detection strategy:
24
24
  #
25
- # 1. empty file: returns 'inode/x-empty'
26
- # 2. nonempty file: if the file is not empty then returns the content type using file command
27
- # 3. invalid file: file command raises error and returns 'application/octet-stream'
25
+ # 1. invalid file_path: returns 'application/octet-stream'
26
+ # 2. empty file: returns 'inode/x-empty'
27
+ # 3. valid file: returns the content type using file command
28
+ # 4. valid file but file commoand raises error: returns 'application/octet-stream'
28
29
 
29
30
  def detect
30
- empty_file? ? EMPTY_CONTENT_TYPE : content_type_from_content
31
+ if !File.exist?(file_path)
32
+ DEFAULT_CONTENT_TYPE
33
+ elsif File.zero?(file_path)
34
+ EMPTY_CONTENT_TYPE
35
+ else
36
+ content_type_from_content
37
+ end
31
38
  end
32
39
 
33
40
  private
34
41
 
35
- def empty_file?
36
- File.exists?(file_path) && File.size(file_path) == 0
37
- end
38
-
39
42
  def content_type_from_content
40
43
  content_type = type_from_file_command
41
44
 
@@ -9,15 +9,17 @@ module ActiveModel
9
9
  end
10
10
 
11
11
  def validate_each(record, attribute, value)
12
- value = JSON.parse(value) if value.is_a?(String) && value.present?
13
- unless value.blank?
12
+ values = parse_values(value)
13
+ unless values.empty?
14
14
  mode = option_value(record, :mode)
15
- content_type = get_content_type(value, mode)
16
15
  allowed_types = option_content_types(record, :allow)
17
16
  forbidden_types = option_content_types(record, :exclude)
18
17
 
19
- validate_whitelist(record, attribute, content_type, allowed_types)
20
- validate_blacklist(record, attribute, content_type, forbidden_types)
18
+ values.each do |value|
19
+ content_type = get_content_type(value, mode)
20
+ validate_whitelist(record, attribute, content_type, allowed_types)
21
+ validate_blacklist(record, attribute, content_type, forbidden_types)
22
+ end
21
23
  end
22
24
  end
23
25
 
@@ -35,6 +37,14 @@ module ActiveModel
35
37
 
36
38
  private
37
39
 
40
+ def parse_values(value)
41
+ return [] unless value.present?
42
+
43
+ value = JSON.parse(value) if value.is_a?(String)
44
+
45
+ Array.wrap(value).reject { |value| value.blank? }
46
+ end
47
+
38
48
  def get_file_path(value)
39
49
  if value.try(:path)
40
50
  value.path
@@ -87,7 +97,10 @@ module ActiveModel
87
97
  end
88
98
 
89
99
  def mark_invalid(record, attribute, error, option_types)
90
- record.errors.add attribute, error, options.merge(types: option_types.join(', '))
100
+ error_options = options.merge(types: option_types.join(', '))
101
+ unless record.errors.added?(attribute, error, error_options)
102
+ record.errors.add attribute, error, error_options
103
+ end
91
104
  end
92
105
  end
93
106
 
@@ -13,15 +13,14 @@ module ActiveModel
13
13
  end
14
14
 
15
15
  def validate_each(record, attribute, value)
16
- value = JSON.parse(value) if value.is_a?(String) && value.present?
17
- unless value.blank?
16
+ values = parse_values(value)
17
+ unless values.empty?
18
18
  options.slice(*CHECKS.keys).each do |option, option_value|
19
- value = OpenStruct.new(value) if value.is_a?(Hash)
20
19
  option_value = option_value.call(record) if option_value.is_a?(Proc)
21
- unless valid_size?(value.size, option, option_value)
20
+ if values.any? { |v| not valid_size?(v.size, option, option_value) }
22
21
  record.errors.add(attribute,
23
22
  "file_size_is_#{option}".to_sym,
24
- filtered_options(value).merge!(detect_error_options(option_value)))
23
+ filtered_options(values).merge!(detect_error_options(option_value)))
25
24
  end
26
25
  end
27
26
  end
@@ -39,6 +38,17 @@ module ActiveModel
39
38
 
40
39
  private
41
40
 
41
+ def parse_values(value)
42
+ return [] unless value.present?
43
+
44
+ value = JSON.parse(value) if value.is_a?(String)
45
+ return [] unless value.present?
46
+
47
+ value = OpenStruct.new(value) if value.is_a?(Hash)
48
+
49
+ Array.wrap(value).reject { |value| value.blank? }
50
+ end
51
+
42
52
  def check_options(klass, options)
43
53
  options.each do |option, value|
44
54
  unless value.is_a?(klass) || value.is_a?(Proc)
@@ -1,3 +1,3 @@
1
1
  module FileValidators
2
- VERSION = '2.1.0'
2
+ VERSION = '2.2.0.beta1'
3
3
  end
@@ -379,4 +379,54 @@ describe 'File Content Type integration with ActiveModel' do
379
379
  it { is_expected.to be_valid }
380
380
  end
381
381
  end
382
+
383
+ context 'image data as array' do
384
+ before :all do
385
+ Person.class_eval do
386
+ Person.reset_callbacks(:validate)
387
+ validates :avatar, file_content_type: { allow: 'image/jpeg' }
388
+ end
389
+ end
390
+
391
+ subject { Person.new }
392
+
393
+ context 'for one invalid content type' do
394
+ before {
395
+ subject.avatar = [
396
+ Rack::Test::UploadedFile.new(@sample_text_path, 'text/plain'),
397
+ Rack::Test::UploadedFile.new(@cute_path, 'image/jpeg')
398
+ ]
399
+ }
400
+ it { is_expected.not_to be_valid }
401
+ end
402
+
403
+ context 'for two invalid content types' do
404
+ before {
405
+ subject.avatar = [
406
+ Rack::Test::UploadedFile.new(@sample_text_path, 'text/plain'),
407
+ Rack::Test::UploadedFile.new(@sample_text_path, 'text/plain')
408
+ ]
409
+ }
410
+
411
+ it 'is invalid and adds just one error' do
412
+ expect(subject).not_to be_valid
413
+ expect(subject.errors.count).to eq 1
414
+ end
415
+ end
416
+
417
+ context 'for valid content type' do
418
+ before {
419
+ subject.avatar = [
420
+ Rack::Test::UploadedFile.new(@cute_path, 'image/jpeg'),
421
+ Rack::Test::UploadedFile.new(@cute_path, 'image/jpeg')
422
+ ]
423
+ }
424
+ it { is_expected.to be_valid }
425
+ end
426
+
427
+ context 'empty array' do
428
+ before { subject.avatar = [] }
429
+ it { is_expected.to be_valid }
430
+ end
431
+ end
382
432
  end
@@ -263,4 +263,67 @@ describe 'File Size Validator integration with ActiveModel' do
263
263
  it { is_expected.to be_valid }
264
264
  end
265
265
  end
266
+
267
+ context 'image data as array' do
268
+ before :all do
269
+ Person.class_eval do
270
+ Person.reset_callbacks(:validate)
271
+ validates :avatar, file_size: { greater_than: 20.kilobytes }
272
+ end
273
+ end
274
+
275
+ subject { Person.new }
276
+
277
+ context 'when size of one file is less than the specified size' do
278
+ before {
279
+ subject.avatar = [
280
+ Rack::Test::UploadedFile.new(@cute_path),
281
+ Rack::Test::UploadedFile.new(@chubby_bubble_path)
282
+ ]
283
+ }
284
+ it { is_expected.not_to be_valid }
285
+ end
286
+
287
+ context 'when size of all files is within the specified size' do
288
+ before {
289
+ subject.avatar = [
290
+ Rack::Test::UploadedFile.new(@cute_path),
291
+ Rack::Test::UploadedFile.new(@cute_path)
292
+ ]
293
+ }
294
+
295
+ it 'is invalid and adds just one error' do
296
+ expect(subject).not_to be_valid
297
+ expect(subject.errors.count).to eq 1
298
+ end
299
+ end
300
+
301
+ context 'when size of all files is less than the specified size' do
302
+ before {
303
+ subject.avatar = [
304
+ Rack::Test::UploadedFile.new(@chubby_bubble_path),
305
+ Rack::Test::UploadedFile.new(@chubby_bubble_path)
306
+ ]
307
+ }
308
+
309
+ it { is_expected.to be_valid }
310
+ end
311
+
312
+ context 'one file' do
313
+ context 'when file size is out of range' do
314
+ before { subject.avatar = [Rack::Test::UploadedFile.new(@cute_path)] }
315
+ it { is_expected.not_to be_valid }
316
+ end
317
+
318
+ context 'when file size within range' do
319
+ before { subject.avatar = [Rack::Test::UploadedFile.new(@chubby_bubble_path)] }
320
+ it { is_expected.to be_valid }
321
+ end
322
+ end
323
+
324
+ context 'empty array' do
325
+ before { subject.avatar = [] }
326
+ it { is_expected.to be_valid }
327
+ end
328
+ end
266
329
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  ENV['RAILS_ENV'] ||= 'test'
2
2
 
3
3
  require 'active_support'
4
+ require 'active_support/deprecation'
4
5
  require 'active_support/core_ext'
5
6
  require 'file_validators'
6
7
  require 'rspec'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: file_validators
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ahmad Musaffa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-09 00:00:00.000000000 Z
11
+ date: 2017-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '3.0'
19
+ version: '3.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '3.0'
26
+ version: '3.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: mime-types
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -119,19 +119,18 @@ files:
119
119
  - ".rspec"
120
120
  - ".travis.yml"
121
121
  - Appraisals
122
- - CHANGELOG.mod
122
+ - CHANGELOG.md
123
123
  - Gemfile
124
124
  - MIT-LICENSE
125
125
  - README.md
126
126
  - README.rdoc
127
127
  - Rakefile
128
128
  - file_validators.gemspec
129
- - gemfiles/activemodel_3.0.gemfile
130
- - gemfiles/activemodel_3.1.gemfile
131
129
  - gemfiles/activemodel_3.2.gemfile
132
130
  - gemfiles/activemodel_4.0.gemfile
133
131
  - gemfiles/activemodel_4.1.gemfile
134
132
  - gemfiles/activemodel_4.2.gemfile
133
+ - gemfiles/activemodel_5.0.gemfile
135
134
  - lib/file_validators.rb
136
135
  - lib/file_validators/locale/en.yml
137
136
  - lib/file_validators/utils/content_type_detector.rb
@@ -170,9 +169,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
170
169
  version: '0'
171
170
  required_rubygems_version: !ruby/object:Gem::Requirement
172
171
  requirements:
173
- - - ">="
172
+ - - ">"
174
173
  - !ruby/object:Gem::Version
175
- version: '0'
174
+ version: 1.3.1
176
175
  requirements: []
177
176
  rubyforge_project:
178
177
  rubygems_version: 2.5.1
data/CHANGELOG.mod DELETED
@@ -1,6 +0,0 @@
1
- # 2.1.0
2
-
3
- * Use autoload for lazy loading of libraries
4
- * Media type spoof valiation is moved to content type detector
5
- * spoofed_file_media_type message isn't needed anymore
6
- * Show logger info and warning
@@ -1,8 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "activemodel", "3.1.12"
7
-
8
- gemspec :path => "../"