file_validators 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d9d77f05c14b168f172952bf2e4418b22e7d716c
4
+ data.tar.gz: 6686bd542bacb69ff3a0db1e7304b8b2ab4d55a4
5
+ SHA512:
6
+ metadata.gz: d5f7393b1bc42819e548ed6f0cbc0633ab66ea5a87451c0ab60c8d50dc2b2036615a88f3548653603010d6661318017869c03d6b472a6338fc470e2e81acc5fc
7
+ data.tar.gz: d602cf19ecae5107bb10148bc7d105118e7c5610f5a099658870c63cb6ecbab4c115e26bc552400499284cecc393ce320fe62c49d1e9b7b723c260594bfbe5dc
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ spec/dummy/db/*.sqlite3
5
+ spec/dummy/db/*.sqlite3-journal
6
+ spec/dummy/log/*.log
7
+ spec/dummy/tmp/
8
+ spec/dummy/.sass-cache
9
+ Gemfile.lock
10
+ gemfiles/*.lock
11
+ coverage/
12
+ /.idea
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
4
+ - 2.0.0
5
+ - 1.9.3
6
+ gemfile:
7
+ - gemfiles/activemodel_4.1.gemfile
8
+ - gemfiles/activemodel_4.0.gemfile
9
+ - gemfiles/activemodel_3.2.gemfile
10
+ - gemfiles/activemodel_3.1.gemfile
11
+ - gemfiles/activemodel_3.0.gemfile
data/Appraisals ADDED
@@ -0,0 +1,19 @@
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
+ appraise 'activemodel-3.2' do
10
+ gem 'activemodel', '3.2.18'
11
+ end
12
+
13
+ appraise 'activemodel-4.0' do
14
+ gem 'activemodel', '4.0.10'
15
+ end
16
+
17
+ appraise 'activemodel-4.1' do
18
+ gem 'activemodel', '4.1.6'
19
+ end
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Declare your gem's dependencies in file_validators.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # Declare any dependencies that are still in development here instead of in
9
+ # your gemspec. These might include edge Rails or gems from your path or
10
+ # Git. Remember to move these dependencies to your gemspec before releasing
11
+ # your gem to rubygems.org.
12
+
13
+ # To use debugger
14
+ # gem 'debugger'
15
+ gem 'appraisal'
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,216 @@
1
+ # File Validators
2
+
3
+ [![Gem Version](http://img.shields.io/gem/v/file_validators.svg)](https://rubygems.org/gems/file_validators)
4
+ [![Build Status](https://travis-ci.org/musaffa/file_validators.svg)](https://travis-ci.org/musaffa/file_validators)
5
+ [![Dependency Status](http://img.shields.io/gemnasium/musaffa/file_validators.svg)](https://gemnasium.com/musaffa/file_validators)
6
+ [![Coverage Status](http://img.shields.io/coveralls/musaffa/file_validators.svg)](https://coveralls.io/r/musaffa/file_validators)
7
+ [![Code Climate](http://img.shields.io/codeclimate/github/musaffa/file_validators.svg)](https://codeclimate.com/github/musaffa/file_validators)
8
+
9
+ File Validators gem adds file size and content type validations to ActiveModel. Any module that uses ActiveModel, for example ActiveRecord, can use these file validators.
10
+
11
+ ## Support
12
+
13
+ * ActiveModel versions: 3 and 4.
14
+ * Rails versions: 3 and 4.
15
+
16
+ ## Installation
17
+
18
+ Add the following to your Gemfile:
19
+
20
+ ```ruby
21
+ gem 'file_validators'
22
+ ```
23
+
24
+ ## Examples
25
+
26
+ ActiveModel example:
27
+
28
+ ```ruby
29
+ class Profile
30
+ include ActiveModel::Validations
31
+
32
+ attr_accessor :avatar
33
+ validates :avatar, file_size: { less_than_or_equal_to: 100.kilobytes },
34
+ file_content_type: { allow: ['image/jpeg', 'image/png', 'image/gif'] }
35
+ end
36
+ ```
37
+ ActiveRecord example:
38
+
39
+ ```ruby
40
+ class Profile < ActiveRecord::Base
41
+ validates :avatar, file_size: { less_than_or_equal_to: 100.kilobytes },
42
+ file_content_type: { allow: ['image/jpeg', 'image/png', 'image/gif'] }
43
+ end
44
+ ```
45
+
46
+ ## API
47
+
48
+ ### File Size Validator:
49
+
50
+ * `in`: A range of bytes
51
+ ```ruby
52
+ validates :avatar, file_size: { in: 100.kilobytes..1.megabyte }
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
63
+ ```ruby
64
+ validates :avatar, file_size: { less_than: 2.gigabytes }
65
+ ```
66
+ * `greater_than`: greater than a number in bytes
67
+ ```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 }
74
+ ```
75
+ The following two examples are equivalent:
76
+ ```ruby
77
+ validates :avatar, file_size: { greater_than_or_equal_to: 500.kilobytes,
78
+ less_than_or_equal_to: 3.megabytes }
79
+ ```
80
+ ```ruby
81
+ validates :avatar, file_size: { in: 500.kilobytes..3.megabytes }
82
+ ```
83
+ If you use `:in`, then the other options will be neglected.
84
+ * `message`: Error message to display. With all the options above except `:in`, you will get `count` as a replacement.
85
+ With `:in` you will get `min` and `max` as replacements.
86
+ `count`, `min` and `max` each will have its value and unit together.
87
+ You can write error messages without using any replacement.
88
+ ```ruby
89
+ validates :avatar, file_size: { less_than: 100.kilobytes,
90
+ message: 'avatar file size should be less than %{count}' }
91
+ ```
92
+ ```ruby
93
+ validates :document, file_size: { in: 1.kilobyte..1.megabyte,
94
+ message: 'document should be within %{min} and %{max}' }
95
+ ```
96
+ * `if`: A lambda or name of an instance method. Validation will only be run if this lambda or method returns true.
97
+ * `unless`: Same as `if` but validates if lambda or method returns false.
98
+
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.
102
+ ```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'] }
109
+ ```
110
+ ```ruby
111
+ # regexp
112
+ validates :avatar, file_content_type: { allow: /^image\/.*/ }
113
+ ```
114
+ ```ruby
115
+ # array of regexps
116
+ validates :attachment, file_content_type: { allow: [/^image\/.*/, /^text\/.*/] }
117
+ ```
118
+ ```ruby
119
+ # array of regexps and strings
120
+ validates :attachment, file_content_type: { allow: [/^image\/.*/, 'video/mp4'] }
121
+ ```
122
+ * `exclude`: Forbidden content types. Can be a single content type or an array. Each type can be a String or a Regexp.
123
+ ```ruby
124
+ # string
125
+ validates :avatar, file_content_type: { exclude: 'image/jpeg' }
126
+ ```
127
+ ```ruby
128
+ # array of strings
129
+ validates :attachment, file_content_type: { exclude: ['image/jpeg', 'text/plain'] }
130
+ ```
131
+ ```ruby
132
+ # regexp
133
+ validates :avatar, file_content_type: { exclude: /^image\/.*/ }
134
+ ```
135
+ ```ruby
136
+ # array of regexps
137
+ validates :attachment, file_content_type: { exclude: [/^image\/.*/, /^text\/.*/] }
138
+ ```
139
+ ```ruby
140
+ # array of regexps and strings
141
+ validates :attachment, file_content_type: { exclude: [/^text\/.*/, 'image/gif'] }
142
+ ```
143
+ You can also combine `:allow` and `:exclude`:
144
+ ```ruby
145
+ # this will allow all the image types except gif
146
+ validates :avatar, file_content_type: { allow: /^image\/.*/, exclude: 'image/gif' }
147
+ ```
148
+ * `message`: The message to display when the uploaded file has an invalid content type.
149
+ You will get `types` as a replacement. You can write error messages without using any replacement.
150
+ ```ruby
151
+ validates :avatar, file_content_type: { allow: ['image/jpeg', 'image/gif'],
152
+ message: 'should have content type %{types}' }
153
+ ```
154
+ ```ruby
155
+ validates :avatar, file_content_type: { allow: ['image/jpeg', 'image/gif'],
156
+ message: 'Avatar only allows jpeg and gif image files' }
157
+ ```
158
+ * `if`: A lambda or name of an instance method. Validation will only be run is this lambda or method returns true.
159
+ * `unless`: Same as `if` but validates if lambda or method returns false.
160
+
161
+ ## i18n Translations
162
+
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.
164
+
165
+ For `:in`, `:allow` and `:exclude` you will have to write your own error messages under `errors.messages`.
166
+
167
+ You can override all of them with the `:message` option.
168
+
169
+ 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`.
171
+ Rails applications already have these translations either in ActiveSupport's locale (Rails 4) or in ActionView's locale (Rails 3).
172
+ In case your setup doesn't have the translations, here's an example for `en`:
173
+
174
+ ```yml
175
+ en:
176
+ number:
177
+ human:
178
+ storage_units:
179
+ format: "%n %u"
180
+ units:
181
+ byte:
182
+ one: "Byte"
183
+ other: "Bytes"
184
+ kb: "KB"
185
+ mb: "MB"
186
+ gb: "GB"
187
+ tb: "TB"
188
+ ```
189
+
190
+ ## Tests
191
+
192
+ ```ruby
193
+ rake
194
+ rake test:unit
195
+ rake test:integration
196
+ ```
197
+
198
+ ## Problems
199
+
200
+ Please use GitHub's [issue tracker](http://github.com/musaffa/file_validations/issues).
201
+
202
+ ## Contributing
203
+
204
+ 1. Fork it
205
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
206
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
207
+ 4. Push to the branch (`git push origin my-new-feature`)
208
+ 5. Create a new Pull Request
209
+
210
+ ## Inspirations
211
+
212
+ * [PaperClip](https://github.com/thoughtbot/paperclip)
213
+
214
+ ## License
215
+
216
+ This project rocks and uses MIT-LICENSE.
data/README.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ = FileValidators
2
+
3
+ This project rocks and uses MIT-LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rspec/core/rake_task'
8
+
9
+ namespace :test do
10
+ RSpec::Core::RakeTask.new(:unit) do |t|
11
+ t.pattern = ['spec/lib/**/*_spec.rb']
12
+ end
13
+
14
+ RSpec::Core::RakeTask.new(:integration) do |t|
15
+ t.pattern = ['spec/integration/**/*_spec.rb']
16
+ end
17
+ end
18
+
19
+ task :default => ['test:unit', 'test:integration']
20
+
21
+ # require 'rdoc/task'
22
+
23
+ # RDoc::Task.new(:rdoc) do |rdoc|
24
+ # rdoc.rdoc_dir = 'rdoc'
25
+ # rdoc.title = 'FileValidators'
26
+ # rdoc.options << '--line-numbers'
27
+ # rdoc.rdoc_files.include('README.rdoc')
28
+ # rdoc.rdoc_files.include('lib/**/*.rb')
29
+ # end
30
+
31
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,26 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+
3
+ require 'file_validators/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'file_validators'
7
+ s.version = FileValidators::VERSION
8
+ s.authors = ['Ahmad Musaffa']
9
+ s.email = ['musaffa_csemm@yahoo.com']
10
+ s.summary = 'ActiveModel file validators'
11
+ s.description = 'Adds file validators to ActiveModel'
12
+ s.homepage = 'https://github.com/musaffa/file_validators'
13
+ s.license = 'MIT'
14
+
15
+ s.files = `git ls-files`.split($/)
16
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ s.test_files = s.files.grep(%r{^spec/})
18
+ s.require_paths = ['lib']
19
+
20
+ s.add_dependency 'activemodel', '>= 3.0'
21
+
22
+ s.add_development_dependency 'rake'
23
+ s.add_development_dependency 'rspec', '~> 3.1.0'
24
+ s.add_development_dependency 'coveralls'
25
+ s.add_development_dependency 'rack-test'
26
+ end
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "activemodel", "3.0.20"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,8 @@
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 => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "activemodel", "3.2.18"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "activemodel", "4.0.10"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "activemodel", "4.1.6"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,73 @@
1
+ module ActiveModel
2
+ module Validations
3
+
4
+ class FileContentTypeValidator < ActiveModel::EachValidator
5
+ def initialize(options)
6
+ super
7
+ end
8
+
9
+ def self.helper_method_name
10
+ :validates_file_content_type
11
+ end
12
+
13
+ def validate_each(record, attribute, value)
14
+ unless value.blank?
15
+ content_type = value.content_type
16
+ validate_whitelist(record, attribute, content_type)
17
+ validate_blacklist(record, attribute, content_type)
18
+ end
19
+ end
20
+
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
24
+ end
25
+ end
26
+
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
30
+ end
31
+ end
32
+
33
+ def mark_invalid(record, attribute, types)
34
+ record.errors.add attribute, :invalid, options.merge(:types => types.join(', '))
35
+ end
36
+
37
+ def allowed_types
38
+ [options[:allow]].flatten.compact
39
+ end
40
+
41
+ def forbidden_types
42
+ [options[:exclude]].flatten.compact
43
+ end
44
+
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
49
+ end
50
+ end
51
+
52
+ module HelperMethods
53
+ # Places ActiveModel validations on the content type of the file
54
+ # assigned. The possible options are:
55
+ # * +allow+: Allowed content types. Can be a single content type
56
+ # or an array. Each type can be a String or a Regexp. It should be
57
+ # noted that Internet Explorer uploads files with content_types that you
58
+ # may not expect. For example, JPEG images are given image/pjpeg and
59
+ # PNGs are image/x-png, so keep that in mind when determining how you
60
+ # match. Allows all by default.
61
+ # * +exclude+: Forbidden content types.
62
+ # * +message+: The message to display when the uploaded file has an invalid
63
+ # content type.
64
+ # * +if+: A lambda or name of an instance method. Validation will only
65
+ # be run is this lambda or method returns true.
66
+ # * +unless+: Same as +if+ but validates if lambda or method returns false.
67
+ def validates_file_content_type(*attr_names)
68
+ validates_with FileContentTypeValidator, _merge_attributes(attr_names)
69
+ end
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,89 @@
1
+ module ActiveModel
2
+ module Validations
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
11
+
12
+ def self.helper_method_name
13
+ :validates_file_size
14
+ end
15
+
16
+ def validate_each(record, attribute, value)
17
+ 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)))
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ 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]'
30
+ end
31
+ end
32
+
33
+ private
34
+
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
40
+ end
41
+ end
42
+
43
+ def clear_options(options)
44
+ AVAILABLE_CHECKS.each do |option|
45
+ options.delete(option)
46
+ end
47
+ end
48
+
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) }
54
+ else
55
+ error_options = { count: human_size(option_value) }
56
+ end
57
+ end
58
+
59
+ def human_size(size)
60
+ if defined?(ActiveSupport::NumberHelper) # Rails 4.0+
61
+ ActiveSupport::NumberHelper.number_to_human_size(size)
62
+ else
63
+ storage_units_format = I18n.translate(:'number.human.storage_units.format', :locale => options[:locale], :raise => true)
64
+ unit = I18n.translate(:'number.human.storage_units.units.byte', :locale => options[:locale], :count => size.to_i, :raise => true)
65
+ storage_units_format.gsub(/%n/, size.to_i.to_s).gsub(/%u/, unit).html_safe
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ module HelperMethods
72
+ # Places ActiveModel validations on the size of the file assigned. The
73
+ # possible options are:
74
+ # * +in+: a Range of bytes (i.e. +1..1.megabyte+),
75
+ # * +less_than_or_equal_to+: equivalent to :in => 0..options[:less_than_or_equal_to]
76
+ # * +greater_than_or_equal_to+: equivalent to :in => options[:greater_than_or_equal_to]..Infinity
77
+ # * +less_than+: less than a number in bytes
78
+ # * +greater_than+: greater than a number in bytes
79
+ # * +message+: error message to display, use :min and :max as replacements
80
+ # * +if+: A lambda or name of an instance method. Validation will only
81
+ # be run if this lambda or method returns true.
82
+ # * +unless+: Same as +if+ but validates if lambda or method returns false.
83
+ def validates_file_size(*attr_names)
84
+ validates_with FileSizeValidator, _merge_attributes(attr_names)
85
+ end
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,3 @@
1
+ module FileValidators
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,3 @@
1
+ require 'active_model'
2
+ require 'file_validators/validators/file_size_validator'
3
+ require 'file_validators/validators/file_content_type_validator'
Binary file
Binary file
Binary file
@@ -0,0 +1 @@
1
+ a sample text