file_validators 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +52 -49
- data/lib/file_validators.rb +3 -0
- data/lib/file_validators/locale/en.yml +12 -0
- data/lib/file_validators/validators/file_content_type_validator.rb +22 -22
- data/lib/file_validators/validators/file_size_validator.rb +34 -28
- data/lib/file_validators/version.rb +1 -1
- data/spec/integration/file_content_type_validation_integration_spec.rb +51 -0
- data/spec/integration/file_size_validator_integration_spec.rb +90 -33
- data/spec/lib/file_validators/validators/file_content_type_validator_spec.rb +30 -0
- data/spec/lib/file_validators/validators/file_size_validator_spec.rb +111 -23
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8e04639d14acd35e4d98938b786d372f5218bdd
|
4
|
+
data.tar.gz: b045b75d86de521365bece751da3b3c24ea890c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a57497456ee76a9f96f1d74e3e5599e43d8d9e68ab120c0bd6b8fe6945a643cc04acb7b97c50ec65f33b34c1352a346bf6564f0c695b67940e10a459b2f5be19
|
7
|
+
data.tar.gz: 4fd2174b5f6a7dae46f0f6ada517f4cb918279286918425948c845dd67d0a744f4e6086eb68ee4b2add6da9849c3a0d2033efa8559e664cdc11c828161dbe9c4
|
data/README.md
CHANGED
@@ -47,40 +47,26 @@ end
|
|
47
47
|
|
48
48
|
### File Size Validator:
|
49
49
|
|
50
|
-
* `in`: A range of bytes
|
50
|
+
* `in`: A range of bytes or a proc that returns a range
|
51
51
|
```ruby
|
52
52
|
validates :avatar, file_size: { in: 100.kilobytes..1.megabyte }
|
53
53
|
```
|
54
|
-
* `
|
55
|
-
```ruby
|
56
|
-
validates :avatar, file_size: { less_than_or_equal_to: 50.bytes }
|
57
|
-
```
|
58
|
-
* `greater_than_or_equal_to`: Greater than or equal to a number in bytes
|
59
|
-
```ruby
|
60
|
-
validates :avatar, file_size: { greater_than_or_equal_to: 50.bytes }
|
61
|
-
```
|
62
|
-
* `less_than`: Less than a number in bytes
|
54
|
+
* `less_than`: Less than a number in bytes or a proc that returns a number
|
63
55
|
```ruby
|
64
56
|
validates :avatar, file_size: { less_than: 2.gigabytes }
|
65
57
|
```
|
66
|
-
* `
|
58
|
+
* `less_than_or_equal_to`: Less than or equal to a number in bytes or a proc that returns a number
|
67
59
|
```ruby
|
68
|
-
validates :avatar, file_size: {
|
69
|
-
```
|
70
|
-
You can also combine these options.
|
71
|
-
```ruby
|
72
|
-
validates :avatar, file_size: { less_than: 1.megabyte,
|
73
|
-
greater_than_or_equal_to: 20.kilobytes }
|
60
|
+
validates :avatar, file_size: { less_than_or_equal_to: 50.bytes }
|
74
61
|
```
|
75
|
-
|
62
|
+
* `greater_than`: greater than a number in bytes or a proc that returns a number
|
76
63
|
```ruby
|
77
|
-
validates :avatar, file_size: {
|
78
|
-
less_than_or_equal_to: 3.megabytes }
|
64
|
+
validates :avatar, file_size: { greater_than: 1.byte }
|
79
65
|
```
|
66
|
+
* `greater_than_or_equal_to`: Greater than or equal to a number in bytes or a proc that returns a number
|
80
67
|
```ruby
|
81
|
-
validates :avatar, file_size: {
|
68
|
+
validates :avatar, file_size: { greater_than_or_equal_to: 50.bytes }
|
82
69
|
```
|
83
|
-
If you use `:in`, then the other options will be neglected.
|
84
70
|
* `message`: Error message to display. With all the options above except `:in`, you will get `count` as a replacement.
|
85
71
|
With `:in` you will get `min` and `max` as replacements.
|
86
72
|
`count`, `min` and `max` each will have its value and unit together.
|
@@ -96,55 +82,53 @@ validates :document, file_size: { in: 1.kilobyte..1.megabyte,
|
|
96
82
|
* `if`: A lambda or name of an instance method. Validation will only be run if this lambda or method returns true.
|
97
83
|
* `unless`: Same as `if` but validates if lambda or method returns false.
|
98
84
|
|
99
|
-
|
100
|
-
|
101
|
-
* `allow`: Allowed content types. Can be a single content type or an array. Each type can be a String or a Regexp. Allows all by default.
|
85
|
+
You can combine different options.
|
102
86
|
```ruby
|
103
|
-
|
104
|
-
|
105
|
-
```
|
106
|
-
```ruby
|
107
|
-
# array of strings
|
108
|
-
validates :attachment, file_content_type: { allow: ['image/jpeg', 'image/png', 'text/plain'] }
|
87
|
+
validates :avatar, file_size: { less_than: 1.megabyte,
|
88
|
+
greater_than_or_equal_to: 20.kilobytes }
|
109
89
|
```
|
90
|
+
The following two examples are equivalent:
|
110
91
|
```ruby
|
111
|
-
|
112
|
-
|
92
|
+
validates :avatar, file_size: { greater_than_or_equal_to: 500.kilobytes,
|
93
|
+
less_than_or_equal_to: 3.megabytes }
|
113
94
|
```
|
114
95
|
```ruby
|
115
|
-
|
116
|
-
validates :attachment, file_content_type: { allow: [/^image\/.*/, /^text\/.*/] }
|
96
|
+
validates :avatar, file_size: { in: 500.kilobytes..3.megabytes }
|
117
97
|
```
|
98
|
+
Options can also take `Proc`/`lambda`:
|
99
|
+
|
118
100
|
```ruby
|
119
|
-
|
120
|
-
validates :attachment, file_content_type: { allow: [/^image\/.*/, 'video/mp4'] }
|
101
|
+
validates :avatar, file_size: { less_than: lambda { |record| record.size_in_bytes } }
|
121
102
|
```
|
122
|
-
|
103
|
+
|
104
|
+
### File Content Type Validator
|
105
|
+
|
106
|
+
* `allow`: Allowed content types. Can be a single content type or an array. Each type can be a String or a Regexp. It also accepts proc. Allows all by default.
|
123
107
|
```ruby
|
124
108
|
# string
|
125
|
-
validates :avatar, file_content_type: {
|
109
|
+
validates :avatar, file_content_type: { allow: 'image/jpeg' }
|
126
110
|
```
|
127
111
|
```ruby
|
128
112
|
# array of strings
|
129
|
-
validates :attachment, file_content_type: {
|
113
|
+
validates :attachment, file_content_type: { allow: ['image/jpeg', 'image/png', 'text/plain'] }
|
130
114
|
```
|
131
115
|
```ruby
|
132
116
|
# regexp
|
133
|
-
validates :avatar, file_content_type: {
|
117
|
+
validates :avatar, file_content_type: { allow: /^image\/.*/ }
|
134
118
|
```
|
135
119
|
```ruby
|
136
120
|
# array of regexps
|
137
|
-
validates :attachment, file_content_type: {
|
121
|
+
validates :attachment, file_content_type: { allow: [/^image\/.*/, /^text\/.*/] }
|
138
122
|
```
|
139
123
|
```ruby
|
140
124
|
# array of regexps and strings
|
141
|
-
validates :attachment, file_content_type: {
|
125
|
+
validates :attachment, file_content_type: { allow: [/^image\/.*/, 'video/mp4'] }
|
142
126
|
```
|
143
|
-
You can also combine `:allow` and `:exclude`:
|
144
127
|
```ruby
|
145
|
-
#
|
146
|
-
validates :
|
128
|
+
# proc/lambda example
|
129
|
+
validates :video, file_content_type: { allow: lambda { |record| record.content_types } }
|
147
130
|
```
|
131
|
+
* `exclude`: Forbidden content types. Can be a single content type or an array. Each type can be a String or a Regexp. It also accepts `proc`. See `:allow` options examples.
|
148
132
|
* `message`: The message to display when the uploaded file has an invalid content type.
|
149
133
|
You will get `types` as a replacement. You can write error messages without using any replacement.
|
150
134
|
```ruby
|
@@ -158,16 +142,35 @@ validates :avatar, file_content_type: { allow: ['image/jpeg', 'image/gif'],
|
|
158
142
|
* `if`: A lambda or name of an instance method. Validation will only be run is this lambda or method returns true.
|
159
143
|
* `unless`: Same as `if` but validates if lambda or method returns false.
|
160
144
|
|
145
|
+
You can combine `:allow` and `:exclude`:
|
146
|
+
```ruby
|
147
|
+
# this will allow all the image types except png and gif
|
148
|
+
validates :avatar, file_content_type: { allow: /^image\/.*/, exclude: ['image/png', 'image/gif'] }
|
149
|
+
```
|
150
|
+
|
161
151
|
## i18n Translations
|
162
152
|
|
163
|
-
|
153
|
+
File Size Errors
|
154
|
+
* `file_size_is_in`: takes `min` and `max` as replacements
|
155
|
+
* `file_size_is_less_than`: takes `count` as replacement
|
156
|
+
* `file_size_is_less_than_or_equal_to`: takes `count` as replacement
|
157
|
+
* `file_size_is_greater_than`: takes `count` as replacement
|
158
|
+
* `file_size_is_greater_than_or_equal_to`: takes `count` as replacement
|
159
|
+
|
160
|
+
Content Type Errors
|
161
|
+
* `allowed_file_content_types`: generated when you have specified allowed types but the content type
|
162
|
+
of the file doesn't match. takes `types` as replacement.
|
163
|
+
* `excluded_file_content_types`: generated when you have specified excluded types and the content type
|
164
|
+
of the file matches anyone of them. takes `types` as replacement.
|
164
165
|
|
165
|
-
|
166
|
+
This gem provides `en` translations for this errors under `errors.messages` namespace.
|
167
|
+
If you want to override and/or create other locales, you can
|
168
|
+
check [this](https://github.com/musaffa/file_validators/blob/master/lib/file_validators/locale/en.yml) out to see how translations are done.
|
166
169
|
|
167
170
|
You can override all of them with the `:message` option.
|
168
171
|
|
169
172
|
For unit format, it will use `number.human.storage_units.format` from your locale.
|
170
|
-
For unit translation,
|
173
|
+
For unit translation, `number.human.storage_units` is used.
|
171
174
|
Rails applications already have these translations either in ActiveSupport's locale (Rails 4) or in ActionView's locale (Rails 3).
|
172
175
|
In case your setup doesn't have the translations, here's an example for `en`:
|
173
176
|
|
data/lib/file_validators.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
1
|
require 'active_model'
|
2
2
|
require 'file_validators/validators/file_size_validator'
|
3
3
|
require 'file_validators/validators/file_content_type_validator'
|
4
|
+
|
5
|
+
locale_path = Dir.glob(File.dirname(__FILE__) + '/file_validators/locale/*.yml')
|
6
|
+
I18n.load_path += locale_path unless I18n.load_path.include?(locale_path)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
en:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
file_size_is_in: ! 'file size must be between %{min} and %{max}'
|
5
|
+
file_size_is_less_than: ! 'file size must be less than %{count}'
|
6
|
+
file_size_is_less_than_or_equal_to: ! 'file size must be less than or equal to %{count}'
|
7
|
+
file_size_is_greater_than: ! 'file size must be greater than %{count}'
|
8
|
+
file_size_is_greater_than_or_equal_to: ! 'file size must be greater than or equal to %{count}'
|
9
|
+
|
10
|
+
allowed_file_content_types: ! 'file should be one of %{types}'
|
11
|
+
excluded_file_content_types: ! 'file cannot be %{types}'
|
12
|
+
|
@@ -1,10 +1,8 @@
|
|
1
1
|
module ActiveModel
|
2
2
|
module Validations
|
3
3
|
|
4
|
-
class FileContentTypeValidator <
|
5
|
-
|
6
|
-
super
|
7
|
-
end
|
4
|
+
class FileContentTypeValidator < EachValidator
|
5
|
+
CHECKS = [:allow, :exclude].freeze
|
8
6
|
|
9
7
|
def self.helper_method_name
|
10
8
|
:validates_file_content_type
|
@@ -18,34 +16,36 @@ module ActiveModel
|
|
18
16
|
end
|
19
17
|
end
|
20
18
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
19
|
+
def check_validity!
|
20
|
+
unless (CHECKS & options.keys).present?
|
21
|
+
raise ArgumentError, 'You must at least pass in :allow or :exclude option'
|
24
22
|
end
|
25
|
-
end
|
26
23
|
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
options.slice(*CHECKS).each do |option, value|
|
25
|
+
unless value.is_a?(String) || value.is_a?(Array) || value.is_a?(Regexp) || value.is_a?(Proc)
|
26
|
+
raise ArgumentError, ":#{option} must be a string, an array, a regex or a proc"
|
27
|
+
end
|
30
28
|
end
|
31
29
|
end
|
32
30
|
|
33
|
-
|
34
|
-
record.errors.add attribute, :invalid, options.merge(:types => types.join(', '))
|
35
|
-
end
|
31
|
+
private
|
36
32
|
|
37
|
-
def
|
38
|
-
[
|
33
|
+
def validate_whitelist(record, attribute, value)
|
34
|
+
allowed_types = [options_call(record, :allow)].flatten.compact
|
35
|
+
if allowed_types.present? && allowed_types.none? { |type| type === value }
|
36
|
+
record.errors.add attribute, :allowed_file_content_types, options.merge(:types => allowed_types.join(', '))
|
37
|
+
end
|
39
38
|
end
|
40
39
|
|
41
|
-
def
|
42
|
-
[
|
40
|
+
def validate_blacklist(record, attribute, value)
|
41
|
+
forbidden_types = [options_call(record, :exclude)].flatten.compact
|
42
|
+
if forbidden_types.present? && forbidden_types.any? { |type| type === value }
|
43
|
+
record.errors.add attribute, :excluded_file_content_types, options.merge(:types => forbidden_types.join(', '))
|
44
|
+
end
|
43
45
|
end
|
44
46
|
|
45
|
-
def
|
46
|
-
|
47
|
-
raise ArgumentError, 'You must pass in either :allow or :exclude to the validator'
|
48
|
-
end
|
47
|
+
def options_call(record, key)
|
48
|
+
options[key].is_a?(Proc) ? options[key].call(record) : options[key]
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -1,13 +1,12 @@
|
|
1
1
|
module ActiveModel
|
2
2
|
module Validations
|
3
3
|
|
4
|
-
class FileSizeValidator <
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
4
|
+
class FileSizeValidator < EachValidator
|
5
|
+
CHECKS = { in: :===,
|
6
|
+
less_than: :<,
|
7
|
+
less_than_or_equal_to: :<=,
|
8
|
+
greater_than: :>,
|
9
|
+
greater_than_or_equal_to: :>= }.freeze
|
11
10
|
|
12
11
|
def self.helper_method_name
|
13
12
|
:validates_file_size
|
@@ -15,44 +14,51 @@ module ActiveModel
|
|
15
14
|
|
16
15
|
def validate_each(record, attribute, value)
|
17
16
|
unless value.blank?
|
18
|
-
options.slice(*
|
19
|
-
|
20
|
-
|
21
|
-
record.errors.add(attribute,
|
17
|
+
options.slice(*CHECKS.keys).each do |option, option_value|
|
18
|
+
option_value = option_value.call(record) if option_value.is_a?(Proc)
|
19
|
+
unless valid_size?(value.size, option, option_value)
|
20
|
+
record.errors.add(attribute,
|
21
|
+
"file_size_is_#{option}".to_sym,
|
22
|
+
filtered_options(value).merge!(detect_error_options(option_value)))
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
28
|
def check_validity!
|
28
|
-
unless (
|
29
|
-
raise ArgumentError, '
|
29
|
+
unless (CHECKS.keys & options.keys).present?
|
30
|
+
raise ArgumentError, 'You must at least pass in one of these options - :in, :less_than,
|
31
|
+
:less_than_or_equal_to, :greater_than and :greater_than_or_equal_to'
|
32
|
+
end
|
33
|
+
|
34
|
+
options.slice(*CHECKS.keys).each do |option, value|
|
35
|
+
unless value.is_a?(Numeric) || value.is_a?(Range) || value.is_a?(Proc)
|
36
|
+
raise ArgumentError, ":#{option} must be a number, a range or a proc"
|
37
|
+
end
|
30
38
|
end
|
31
39
|
end
|
32
40
|
|
33
41
|
private
|
34
42
|
|
35
|
-
def
|
36
|
-
if
|
37
|
-
|
38
|
-
|
39
|
-
|
43
|
+
def valid_size?(size, option, option_value)
|
44
|
+
if option_value.is_a?(Range)
|
45
|
+
option_value.send(CHECKS[option], size)
|
46
|
+
else
|
47
|
+
size.send(CHECKS[option], option_value)
|
40
48
|
end
|
41
49
|
end
|
42
50
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
51
|
+
def filtered_options(value)
|
52
|
+
filtered = options.except(*CHECKS.keys)
|
53
|
+
filtered[:value] = value
|
54
|
+
filtered
|
47
55
|
end
|
48
56
|
|
49
|
-
def detect_error_options(
|
50
|
-
if
|
51
|
-
|
52
|
-
min = options[:greater_than_or_equal_to]
|
53
|
-
error_options = { min: human_size(min), max: human_size(max) }
|
57
|
+
def detect_error_options(option_value)
|
58
|
+
if option_value.is_a?(Range)
|
59
|
+
{ min: human_size(option_value.min), max: human_size(option_value.max) }
|
54
60
|
else
|
55
|
-
|
61
|
+
{ count: human_size(option_value) }
|
56
62
|
end
|
57
63
|
end
|
58
64
|
|
@@ -91,6 +91,34 @@ describe 'File Content Type integration with ActiveModel' do
|
|
91
91
|
it { is_expected.not_to be_valid }
|
92
92
|
end
|
93
93
|
end
|
94
|
+
|
95
|
+
context 'as a proc' do
|
96
|
+
before :all do
|
97
|
+
Person.class_eval do
|
98
|
+
Person.reset_callbacks(:validate)
|
99
|
+
validates :avatar, file_content_type: { allow: lambda { |record| ['image/jpeg', 'text/plain'] } }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
subject { Person.new }
|
104
|
+
|
105
|
+
context 'with allowed types' do
|
106
|
+
it 'validates jpeg' do
|
107
|
+
subject.avatar = Rack::Test::UploadedFile.new(@cute_path, 'image/jpeg')
|
108
|
+
expect(subject).to be_valid
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'validates text file' do
|
112
|
+
subject.avatar = Rack::Test::UploadedFile.new(@sample_text_path, 'text/plain')
|
113
|
+
expect(subject).to be_valid
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'with a disallowed type' do
|
118
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@chubby_cute_path, 'image/png') }
|
119
|
+
it { is_expected.not_to be_valid }
|
120
|
+
end
|
121
|
+
end
|
94
122
|
end
|
95
123
|
|
96
124
|
context ':exclude option' do
|
@@ -170,6 +198,29 @@ describe 'File Content Type integration with ActiveModel' do
|
|
170
198
|
end
|
171
199
|
end
|
172
200
|
end
|
201
|
+
|
202
|
+
context 'as a proc' do
|
203
|
+
before :all do
|
204
|
+
Person.class_eval do
|
205
|
+
Person.reset_callbacks(:validate)
|
206
|
+
validates :avatar, file_content_type: { exclude: lambda { |record| /^image\/.*/ } }
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
subject { Person.new }
|
211
|
+
|
212
|
+
context 'with an allowed type' do
|
213
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@sample_text_path, 'text/plain') }
|
214
|
+
it { is_expected.to be_valid }
|
215
|
+
end
|
216
|
+
|
217
|
+
context 'with a disallowed types' do
|
218
|
+
it 'invalidates jpeg image file' do
|
219
|
+
subject.avatar = Rack::Test::UploadedFile.new(@cute_path, 'image/jpeg')
|
220
|
+
expect(subject).not_to be_valid
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
173
224
|
end
|
174
225
|
|
175
226
|
context ':allow and :exclude combined' do
|
@@ -14,55 +14,112 @@ describe 'File Size Validator integration with ActiveModel' do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
context ':in option' do
|
17
|
-
|
18
|
-
|
19
|
-
Person.
|
20
|
-
|
17
|
+
context 'as a range' do
|
18
|
+
before :all do
|
19
|
+
Person.class_eval do
|
20
|
+
Person.reset_callbacks(:validate)
|
21
|
+
validates :avatar, file_size: { in: 20.kilobytes..40.kilobytes }
|
22
|
+
end
|
21
23
|
end
|
22
|
-
end
|
23
24
|
|
24
|
-
|
25
|
+
subject { Person.new }
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
context 'when file size is out of range' do
|
28
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@cute_path) }
|
29
|
+
it { is_expected.not_to be_valid }
|
30
|
+
end
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
context 'when file size is out of range' do
|
33
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@chubby_cute_path) }
|
34
|
+
it { is_expected.not_to be_valid }
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when file size within range' do
|
38
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@chubby_bubble_path) }
|
39
|
+
it { is_expected.to be_valid }
|
40
|
+
end
|
34
41
|
end
|
35
42
|
|
36
|
-
context '
|
37
|
-
before
|
38
|
-
|
43
|
+
context 'as a proc' do
|
44
|
+
before :all do
|
45
|
+
Person.class_eval do
|
46
|
+
Person.reset_callbacks(:validate)
|
47
|
+
validates :avatar, file_size: { in: lambda { |record| 20.kilobytes..40.kilobytes } }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
subject { Person.new }
|
52
|
+
|
53
|
+
context 'when file size is out of range' do
|
54
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@cute_path) }
|
55
|
+
it { is_expected.not_to be_valid }
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when file size is out of range' do
|
59
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@chubby_cute_path) }
|
60
|
+
it { is_expected.not_to be_valid }
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when file size within range' do
|
64
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@chubby_bubble_path) }
|
65
|
+
it { is_expected.to be_valid }
|
66
|
+
end
|
39
67
|
end
|
40
68
|
end
|
41
69
|
|
42
70
|
context ':greater_than and :less_than option' do
|
43
|
-
|
44
|
-
|
45
|
-
Person.
|
46
|
-
|
47
|
-
|
71
|
+
context 'as numbers' do
|
72
|
+
before :all do
|
73
|
+
Person.class_eval do
|
74
|
+
Person.reset_callbacks(:validate)
|
75
|
+
validates :avatar, file_size: { greater_than: 20.kilobytes,
|
76
|
+
less_than: 40.kilobytes }
|
77
|
+
end
|
48
78
|
end
|
49
|
-
end
|
50
79
|
|
51
|
-
|
80
|
+
subject { Person.new }
|
52
81
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
82
|
+
context 'when file size is out of range' do
|
83
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@cute_path) }
|
84
|
+
it { is_expected.not_to be_valid }
|
85
|
+
end
|
57
86
|
|
58
|
-
|
59
|
-
|
60
|
-
|
87
|
+
context 'when file size is out of range' do
|
88
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@chubby_cute_path) }
|
89
|
+
it { is_expected.not_to be_valid }
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when file size within range' do
|
93
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@chubby_bubble_path) }
|
94
|
+
it { is_expected.to be_valid }
|
95
|
+
end
|
61
96
|
end
|
62
97
|
|
63
|
-
context '
|
64
|
-
before
|
65
|
-
|
98
|
+
context 'as procs' do
|
99
|
+
before :all do
|
100
|
+
Person.class_eval do
|
101
|
+
Person.reset_callbacks(:validate)
|
102
|
+
validates :avatar, file_size: { greater_than: lambda { |record| 20.kilobytes },
|
103
|
+
less_than: lambda { |record| 40.kilobytes } }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
subject { Person.new }
|
108
|
+
|
109
|
+
context 'when file size is out of range' do
|
110
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@cute_path) }
|
111
|
+
it { is_expected.not_to be_valid }
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'when file size is out of range' do
|
115
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@chubby_cute_path) }
|
116
|
+
it { is_expected.not_to be_valid }
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'when file size within range' do
|
120
|
+
before { subject.avatar = Rack::Test::UploadedFile.new(@chubby_bubble_path) }
|
121
|
+
it { is_expected.to be_valid }
|
122
|
+
end
|
66
123
|
end
|
67
124
|
end
|
68
125
|
|
@@ -28,6 +28,11 @@ describe ActiveModel::Validations::FileContentTypeValidator do
|
|
28
28
|
before { build_validator allow: ['image/png', 'image/jpg', 'image/jpeg'] }
|
29
29
|
it { is_expected.to allow_file_content_type('image/png', @validator) }
|
30
30
|
end
|
31
|
+
|
32
|
+
context 'as a proc' do
|
33
|
+
before { build_validator allow: lambda { |record| ['image/png', 'image/jpg', 'image/jpeg'] } }
|
34
|
+
it { is_expected.to allow_file_content_type('image/png', @validator) }
|
35
|
+
end
|
31
36
|
end
|
32
37
|
|
33
38
|
context 'with a disallowed type' do
|
@@ -40,6 +45,11 @@ describe ActiveModel::Validations::FileContentTypeValidator do
|
|
40
45
|
before { build_validator allow: /^text\/.*/ }
|
41
46
|
it { is_expected.not_to allow_file_content_type('image/png', @validator) }
|
42
47
|
end
|
48
|
+
|
49
|
+
context 'as a proc' do
|
50
|
+
before { build_validator allow: lambda { |record| /^text\/.*/ } }
|
51
|
+
it { is_expected.not_to allow_file_content_type('image/png', @validator) }
|
52
|
+
end
|
43
53
|
|
44
54
|
context 'with :message option' do
|
45
55
|
context 'without interpolation' do
|
@@ -55,6 +65,11 @@ describe ActiveModel::Validations::FileContentTypeValidator do
|
|
55
65
|
message: 'Avatar should have content type image/png') }
|
56
66
|
end
|
57
67
|
end
|
68
|
+
|
69
|
+
context 'default message' do
|
70
|
+
before { build_validator allow: 'image/png' }
|
71
|
+
it { is_expected.not_to allow_file_content_type('image/jpeg', @validator, message: 'Avatar file should be one of image/png') }
|
72
|
+
end
|
58
73
|
end
|
59
74
|
end
|
60
75
|
|
@@ -74,6 +89,11 @@ describe ActiveModel::Validations::FileContentTypeValidator do
|
|
74
89
|
before { build_validator exclude: ['image/png', 'image/jpg', 'image/jpeg'] }
|
75
90
|
it { is_expected.to allow_file_content_type('image/gif', @validator) }
|
76
91
|
end
|
92
|
+
|
93
|
+
context 'as a proc' do
|
94
|
+
before { build_validator exclude: lambda { |record| ['image/png', 'image/jpg', 'image/jpeg'] } }
|
95
|
+
it { is_expected.to allow_file_content_type('image/gif', @validator) }
|
96
|
+
end
|
77
97
|
end
|
78
98
|
|
79
99
|
context 'with a disallowed type' do
|
@@ -86,6 +106,11 @@ describe ActiveModel::Validations::FileContentTypeValidator do
|
|
86
106
|
before { build_validator exclude: /^text\/.*/ }
|
87
107
|
it { is_expected.not_to allow_file_content_type('text/plain', @validator) }
|
88
108
|
end
|
109
|
+
|
110
|
+
context 'as an proc' do
|
111
|
+
before { build_validator exclude: lambda { |record| /^text\/.*/ } }
|
112
|
+
it { is_expected.not_to allow_file_content_type('text/plain', @validator) }
|
113
|
+
end
|
89
114
|
|
90
115
|
context 'with :message option' do
|
91
116
|
context 'without interpolation' do
|
@@ -101,6 +126,11 @@ describe ActiveModel::Validations::FileContentTypeValidator do
|
|
101
126
|
message: 'Avatar should not have content type image/jpeg') }
|
102
127
|
end
|
103
128
|
end
|
129
|
+
|
130
|
+
context 'default message' do
|
131
|
+
before { build_validator exclude: 'image/png' }
|
132
|
+
it { is_expected.not_to allow_file_content_type('image/png', @validator, message: 'Avatar file cannot be image/png') }
|
133
|
+
end
|
104
134
|
end
|
105
135
|
end
|
106
136
|
|
@@ -25,49 +25,108 @@ describe ActiveModel::Validations::FileSizeValidator do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
context 'with :in option' do
|
28
|
-
|
28
|
+
context 'as a range' do
|
29
|
+
before { build_validator in: (5.kilobytes..10.kilobytes) }
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
it { is_expected.to allow_file_size(7.kilobytes, @validator) }
|
32
|
+
it { is_expected.not_to allow_file_size(4.kilobytes, @validator) }
|
33
|
+
it { is_expected.not_to allow_file_size(11.kilobytes, @validator) }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'as a proc' do
|
37
|
+
before { build_validator in: lambda { |record| (5.kilobytes..10.kilobytes) } }
|
38
|
+
|
39
|
+
it { is_expected.to allow_file_size(7.kilobytes, @validator) }
|
40
|
+
it { is_expected.not_to allow_file_size(4.kilobytes, @validator) }
|
41
|
+
it { is_expected.not_to allow_file_size(11.kilobytes, @validator) }
|
42
|
+
end
|
33
43
|
end
|
34
44
|
|
35
45
|
context 'with :greater_than_or_equal_to option' do
|
36
|
-
|
46
|
+
context 'as a number' do
|
47
|
+
before { build_validator greater_than_or_equal_to: 10.kilobytes }
|
37
48
|
|
38
|
-
|
39
|
-
|
40
|
-
|
49
|
+
it { is_expected.to allow_file_size(11.kilobytes, @validator) }
|
50
|
+
it { is_expected.to allow_file_size(10.kilobytes, @validator) }
|
51
|
+
it { is_expected.not_to allow_file_size(9.kilobytes, @validator) }
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'as a proc' do
|
55
|
+
before { build_validator greater_than_or_equal_to: lambda { |record| 10.kilobytes } }
|
56
|
+
|
57
|
+
it { is_expected.to allow_file_size(11.kilobytes, @validator) }
|
58
|
+
it { is_expected.to allow_file_size(10.kilobytes, @validator) }
|
59
|
+
it { is_expected.not_to allow_file_size(9.kilobytes, @validator) }
|
60
|
+
end
|
41
61
|
end
|
42
62
|
|
43
63
|
context 'with :less_than_or_equal_to option' do
|
44
|
-
|
64
|
+
context 'as a number' do
|
65
|
+
before { build_validator less_than_or_equal_to: 10.kilobytes }
|
45
66
|
|
46
|
-
|
47
|
-
|
48
|
-
|
67
|
+
it { is_expected.to allow_file_size(9.kilobytes, @validator) }
|
68
|
+
it { is_expected.to allow_file_size(10.kilobytes, @validator) }
|
69
|
+
it { is_expected.not_to allow_file_size(11.kilobytes, @validator) }
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'as a proc' do
|
73
|
+
before { build_validator less_than_or_equal_to: lambda { |record| 10.kilobytes } }
|
74
|
+
|
75
|
+
it { is_expected.to allow_file_size(9.kilobytes, @validator) }
|
76
|
+
it { is_expected.to allow_file_size(10.kilobytes, @validator) }
|
77
|
+
it { is_expected.not_to allow_file_size(11.kilobytes, @validator) }
|
78
|
+
end
|
49
79
|
end
|
50
80
|
|
51
81
|
context 'with :greater_than option' do
|
52
|
-
|
82
|
+
context 'as a number' do
|
83
|
+
before { build_validator greater_than: 10.kilobytes }
|
84
|
+
|
85
|
+
it { is_expected.to allow_file_size(11.kilobytes, @validator) }
|
86
|
+
it { is_expected.not_to allow_file_size(10.kilobytes, @validator) }
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'as a proc' do
|
90
|
+
before { build_validator greater_than: lambda { |record| 10.kilobytes } }
|
53
91
|
|
54
|
-
|
55
|
-
|
92
|
+
it { is_expected.to allow_file_size(11.kilobytes, @validator) }
|
93
|
+
it { is_expected.not_to allow_file_size(10.kilobytes, @validator) }
|
94
|
+
end
|
56
95
|
end
|
57
96
|
|
58
97
|
context 'with :less_than option' do
|
59
|
-
|
98
|
+
context 'as a number' do
|
99
|
+
before { build_validator less_than: 10.kilobytes }
|
100
|
+
|
101
|
+
it { is_expected.to allow_file_size(9.kilobytes, @validator) }
|
102
|
+
it { is_expected.not_to allow_file_size(10.kilobytes, @validator) }
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'as a proc' do
|
106
|
+
before { build_validator less_than: lambda { |record| 10.kilobytes } }
|
60
107
|
|
61
|
-
|
62
|
-
|
108
|
+
it { is_expected.to allow_file_size(9.kilobytes, @validator) }
|
109
|
+
it { is_expected.not_to allow_file_size(10.kilobytes, @validator) }
|
110
|
+
end
|
63
111
|
end
|
64
112
|
|
65
113
|
context 'with :greater_than and :less_than option' do
|
66
|
-
|
114
|
+
context 'as a number' do
|
115
|
+
before { build_validator greater_than: 5.kilobytes, less_than: 10.kilobytes }
|
116
|
+
|
117
|
+
it { is_expected.to allow_file_size(7.kilobytes, @validator) }
|
118
|
+
it { is_expected.not_to allow_file_size(5.kilobytes, @validator) }
|
119
|
+
it { is_expected.not_to allow_file_size(10.kilobytes, @validator) }
|
120
|
+
end
|
67
121
|
|
68
|
-
|
69
|
-
|
70
|
-
|
122
|
+
context 'as a proc' do
|
123
|
+
before { build_validator greater_than: lambda { |record| 5.kilobytes },
|
124
|
+
less_than: lambda { |record| 10.kilobytes } }
|
125
|
+
|
126
|
+
it { is_expected.to allow_file_size(7.kilobytes, @validator) }
|
127
|
+
it { is_expected.not_to allow_file_size(5.kilobytes, @validator) }
|
128
|
+
it { is_expected.not_to allow_file_size(10.kilobytes, @validator) }
|
129
|
+
end
|
71
130
|
end
|
72
131
|
|
73
132
|
context 'with :message option' do
|
@@ -81,6 +140,35 @@ describe ActiveModel::Validations::FileSizeValidator do
|
|
81
140
|
message: "Avatar is invalid. (Between #{@storage_units[5120]} and #{@storage_units[10240]} please.)") }
|
82
141
|
end
|
83
142
|
|
143
|
+
context 'default error message' do
|
144
|
+
context 'given :in options' do
|
145
|
+
before { build_validator in: 5.kilobytes..10.kilobytes }
|
146
|
+
|
147
|
+
it { is_expected.not_to allow_file_size(11.kilobytes, @validator,
|
148
|
+
message: "Avatar file size must be between #{@storage_units[5120]} and #{@storage_units[10240]}") }
|
149
|
+
it { is_expected.not_to allow_file_size(4.kilobytes, @validator,
|
150
|
+
message: "Avatar file size must be between #{@storage_units[5120]} and #{@storage_units[10240]}") }
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'given :greater_than and :less_than options' do
|
154
|
+
before { build_validator greater_than: 5.kilobytes, less_than: 10.kilobytes }
|
155
|
+
|
156
|
+
it { is_expected.not_to allow_file_size(11.kilobytes, @validator,
|
157
|
+
message: "Avatar file size must be less than #{@storage_units[10240]}") }
|
158
|
+
it { is_expected.not_to allow_file_size(4.kilobytes, @validator,
|
159
|
+
message: "Avatar file size must be greater than #{@storage_units[5120]}") }
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'given :greater_than_or_equal_to and :less_than_or_equal_to options' do
|
163
|
+
before { build_validator greater_than_or_equal_to: 5.kilobytes, less_than_or_equal_to: 10.kilobytes }
|
164
|
+
|
165
|
+
it { is_expected.not_to allow_file_size(11.kilobytes, @validator,
|
166
|
+
message: "Avatar file size must be less than or equal to #{@storage_units[10240]}") }
|
167
|
+
it { is_expected.not_to allow_file_size(4.kilobytes, @validator,
|
168
|
+
message: "Avatar file size must be greater than or equal to #{@storage_units[5120]}") }
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
84
172
|
|
85
173
|
context 'using the helper' do
|
86
174
|
before { Dummy.validates_file_size :avatar, in: (5.kilobytes..10.kilobytes) }
|
@@ -95,7 +183,7 @@ describe ActiveModel::Validations::FileSizeValidator do
|
|
95
183
|
expect { build_validator message: 'Some message' }.to raise_error(ArgumentError)
|
96
184
|
end
|
97
185
|
|
98
|
-
(ActiveModel::Validations::FileSizeValidator::
|
186
|
+
(ActiveModel::Validations::FileSizeValidator::CHECKS.keys).each do |argument|
|
99
187
|
it "does not raise argument error if #{argument} was given" do
|
100
188
|
expect { build_validator argument => 5.kilobytes }.not_to raise_error
|
101
189
|
end
|
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: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ahmad Musaffa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -102,6 +102,7 @@ files:
|
|
102
102
|
- gemfiles/activemodel_4.0.gemfile
|
103
103
|
- gemfiles/activemodel_4.1.gemfile
|
104
104
|
- lib/file_validators.rb
|
105
|
+
- lib/file_validators/locale/en.yml
|
105
106
|
- lib/file_validators/validators/file_content_type_validator.rb
|
106
107
|
- lib/file_validators/validators/file_size_validator.rb
|
107
108
|
- lib/file_validators/version.rb
|
@@ -156,4 +157,3 @@ test_files:
|
|
156
157
|
- spec/spec_helper.rb
|
157
158
|
- spec/support/matchers/allow_content_type.rb
|
158
159
|
- spec/support/matchers/allow_file_size.rb
|
159
|
-
has_rdoc:
|