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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d9d77f05c14b168f172952bf2e4418b22e7d716c
4
- data.tar.gz: 6686bd542bacb69ff3a0db1e7304b8b2ab4d55a4
3
+ metadata.gz: e8e04639d14acd35e4d98938b786d372f5218bdd
4
+ data.tar.gz: b045b75d86de521365bece751da3b3c24ea890c8
5
5
  SHA512:
6
- metadata.gz: d5f7393b1bc42819e548ed6f0cbc0633ab66ea5a87451c0ab60c8d50dc2b2036615a88f3548653603010d6661318017869c03d6b472a6338fc470e2e81acc5fc
7
- data.tar.gz: d602cf19ecae5107bb10148bc7d105118e7c5610f5a099658870c63cb6ecbab4c115e26bc552400499284cecc393ce320fe62c49d1e9b7b723c260594bfbe5dc
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
- * `less_than_or_equal_to`: Less than or equal to a number in bytes
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
- * `greater_than`: greater than a number in bytes
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: { greater_than: 1.byte }
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
- The following two examples are equivalent:
62
+ * `greater_than`: greater than a number in bytes or a proc that returns a number
76
63
  ```ruby
77
- validates :avatar, file_size: { greater_than_or_equal_to: 500.kilobytes,
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: { in: 500.kilobytes..3.megabytes }
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
- ### File Content Type Validator
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
- # string
104
- validates :avatar, file_content_type: { allow: 'image/jpeg' }
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
- # regexp
112
- validates :avatar, file_content_type: { allow: /^image\/.*/ }
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
- # array of regexps
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
- # array of regexps and strings
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
- * `exclude`: Forbidden content types. Can be a single content type or an array. Each type can be a String or a Regexp.
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: { exclude: 'image/jpeg' }
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: { exclude: ['image/jpeg', 'text/plain'] }
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: { exclude: /^image\/.*/ }
117
+ validates :avatar, file_content_type: { allow: /^image\/.*/ }
134
118
  ```
135
119
  ```ruby
136
120
  # array of regexps
137
- validates :attachment, file_content_type: { exclude: [/^image\/.*/, /^text\/.*/] }
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: { exclude: [/^text\/.*/, 'image/gif'] }
125
+ validates :attachment, file_content_type: { allow: [/^image\/.*/, 'video/mp4'] }
142
126
  ```
143
- You can also combine `:allow` and `:exclude`:
144
127
  ```ruby
145
- # this will allow all the image types except gif
146
- validates :avatar, file_content_type: { allow: /^image\/.*/, exclude: 'image/gif' }
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
- By default, `FileSizeValidator` will use the error messages of `:less_than`, `:greater_than_or_equal_to` etc from `errors.messages` of your locale. `errors.messages` translation is available under ActiveModel's locale.
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
- For `:in`, `:allow` and `:exclude` you will have to write your own error messages under `errors.messages`.
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, it will use `number.human.storage_units`.
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
 
@@ -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 < ActiveModel::EachValidator
5
- def initialize(options)
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 validate_whitelist(record, attribute, value)
22
- if allowed_types.present? && allowed_types.none? { |type| type === value }
23
- mark_invalid record, attribute, allowed_types
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
- def validate_blacklist(record, attribute, value)
28
- if forbidden_types.present? && forbidden_types.any? { |type| type === value }
29
- mark_invalid record, attribute, forbidden_types
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
- def mark_invalid(record, attribute, types)
34
- record.errors.add attribute, :invalid, options.merge(:types => types.join(', '))
35
- end
31
+ private
36
32
 
37
- def allowed_types
38
- [options[:allow]].flatten.compact
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 forbidden_types
42
- [options[:exclude]].flatten.compact
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 check_validity!
46
- unless options.has_key?(:allow) || options.has_key?(:exclude)
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 < ActiveModel::Validations::NumericalityValidator
5
- AVAILABLE_CHECKS = [:less_than, :less_than_or_equal_to, :greater_than, :greater_than_or_equal_to].freeze
6
-
7
- def initialize(options)
8
- extract_options(options)
9
- super
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(*AVAILABLE_CHECKS).each do |option, option_value|
19
- unless value.size.send(CHECKS[option], option_value)
20
- error_message_key = options[:in] ? :in : option
21
- record.errors.add(attribute, error_message_key, filtered_options(value).merge!(detect_error_options(option, option_value)))
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 (AVAILABLE_CHECKS + [:in]).any? { |argument| options.has_key?(argument) }
29
- raise ArgumentError, 'List of allowed options - [:in, :less_than, :greater_than, :less_than_or_equal_to, :greater_than_or_equal_to]'
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 extract_options(options)
36
- if range = options[:in]
37
- raise ArgumentError, ':in must be a Range' unless range.is_a?(Range)
38
- clear_options(options)
39
- options[:less_than_or_equal_to], options[:greater_than_or_equal_to] = range.max, range.min
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 clear_options(options)
44
- AVAILABLE_CHECKS.each do |option|
45
- options.delete(option)
46
- end
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(option, option_value)
50
- if options[:in]
51
- max = options[:less_than_or_equal_to]
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
- error_options = { count: human_size(option_value) }
61
+ { count: human_size(option_value) }
56
62
  end
57
63
  end
58
64
 
@@ -1,3 +1,3 @@
1
1
  module FileValidators
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -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
- before :all do
18
- Person.class_eval do
19
- Person.reset_callbacks(:validate)
20
- validates :avatar, file_size: { in: 20.kilobytes..40.kilobytes }
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
- subject { Person.new }
25
+ subject { Person.new }
25
26
 
26
- context 'when file size is out of range' do
27
- before { subject.avatar = Rack::Test::UploadedFile.new(@cute_path) }
28
- it { is_expected.not_to be_valid }
29
- end
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
- context 'when file size is out of range' do
32
- before { subject.avatar = Rack::Test::UploadedFile.new(@chubby_cute_path) }
33
- it { is_expected.not_to be_valid }
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 'when file size within range' do
37
- before { subject.avatar = Rack::Test::UploadedFile.new(@chubby_bubble_path) }
38
- it { is_expected.to be_valid }
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
- before :all do
44
- Person.class_eval do
45
- Person.reset_callbacks(:validate)
46
- validates :avatar, file_size: { greater_than: 20.kilobytes,
47
- less_than: 40.kilobytes }
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
- subject { Person.new }
80
+ subject { Person.new }
52
81
 
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
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
- 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 }
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 'when file size within range' do
64
- before { subject.avatar = Rack::Test::UploadedFile.new(@chubby_bubble_path) }
65
- it { is_expected.to be_valid }
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
- before { build_validator in: (5.kilobytes..10.kilobytes) }
28
+ context 'as a range' do
29
+ before { build_validator in: (5.kilobytes..10.kilobytes) }
29
30
 
30
- it { is_expected.to allow_file_size(7.kilobytes, @validator) }
31
- it { is_expected.not_to allow_file_size(4.kilobytes, @validator) }
32
- it { is_expected.not_to allow_file_size(11.kilobytes, @validator) }
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
- before { build_validator greater_than_or_equal_to: 10.kilobytes }
46
+ context 'as a number' do
47
+ before { build_validator greater_than_or_equal_to: 10.kilobytes }
37
48
 
38
- it { is_expected.to allow_file_size(11.kilobytes, @validator) }
39
- it { is_expected.to allow_file_size(10.kilobytes, @validator) }
40
- it { is_expected.not_to allow_file_size(9.kilobytes, @validator) }
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
- before { build_validator less_than_or_equal_to: 10.kilobytes }
64
+ context 'as a number' do
65
+ before { build_validator less_than_or_equal_to: 10.kilobytes }
45
66
 
46
- it { is_expected.to allow_file_size(9.kilobytes, @validator) }
47
- it { is_expected.to allow_file_size(10.kilobytes, @validator) }
48
- it { is_expected.not_to allow_file_size(11.kilobytes, @validator) }
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
- before { build_validator greater_than: 10.kilobytes }
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
- it { is_expected.to allow_file_size(11.kilobytes, @validator) }
55
- it { is_expected.not_to allow_file_size(10.kilobytes, @validator) }
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
- before { build_validator less_than: 10.kilobytes }
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
- it { is_expected.to allow_file_size(9.kilobytes, @validator) }
62
- it { is_expected.not_to allow_file_size(10.kilobytes, @validator) }
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
- before { build_validator greater_than: 5.kilobytes, less_than: 10.kilobytes }
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
- it { is_expected.to allow_file_size(7.kilobytes, @validator) }
69
- it { is_expected.not_to allow_file_size(5.kilobytes, @validator) }
70
- it { is_expected.not_to allow_file_size(10.kilobytes, @validator) }
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::AVAILABLE_CHECKS).each do |argument|
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.0.0
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-10 00:00:00.000000000 Z
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: