{"id":13879916,"url":"https://github.com/musaffa/file_validators","last_synced_at":"2025-05-16T10:05:51.636Z","repository":{"id":21656447,"uuid":"24977283","full_name":"musaffa/file_validators","owner":"musaffa","description":"Adds file validators to ActiveModel.","archived":false,"fork":false,"pushed_at":"2021-09-28T18:08:00.000Z","size":196,"stargazers_count":259,"open_issues_count":15,"forks_count":24,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-05-16T10:04:58.351Z","etag":null,"topics":["activemodel","rails"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"emaag/interactive-decision-tree","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/musaffa.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-10-09T06:53:30.000Z","updated_at":"2025-03-24T14:53:13.000Z","dependencies_parsed_at":"2022-09-01T14:04:30.584Z","dependency_job_id":null,"html_url":"https://github.com/musaffa/file_validators","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/musaffa%2Ffile_validators","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/musaffa%2Ffile_validators/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/musaffa%2Ffile_validators/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/musaffa%2Ffile_validators/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/musaffa","download_url":"https://codeload.github.com/musaffa/file_validators/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254509477,"owners_count":22082891,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activemodel","rails"],"created_at":"2024-08-06T08:02:38.915Z","updated_at":"2025-05-16T10:05:51.609Z","avatar_url":"https://github.com/musaffa.png","language":"Ruby","readme":"# File Validators\n\n[![Gem Version](https://badge.fury.io/rb/file_validators.svg)](http://badge.fury.io/rb/file_validators)\n[![Build Status](https://travis-ci.org/musaffa/file_validators.svg)](https://travis-ci.org/musaffa/file_validators)\n[![Coverage Status](https://coveralls.io/repos/musaffa/file_validators/badge.png)](https://coveralls.io/r/musaffa/file_validators)\n[![Code Climate](https://codeclimate.com/github/musaffa/file_validators/badges/gpa.svg)](https://codeclimate.com/github/musaffa/file_validators)\n[![Inline docs](http://inch-ci.org/github/musaffa/file_validators.svg)](http://inch-ci.org/github/musaffa/file_validators)\n\nFile Validators gem adds file size and content type validations to ActiveModel.\nAny module that uses ActiveModel, for example ActiveRecord, can use these file validators.\n\n## Support\n\n* ActiveModel versions: 3.2, 4, 5 and 6.\n* Rails versions: 3.2, 4, 5 and 6.\n\nAs of version `2.2`, activemodel 3.0 and 3.1 will no longer be supported.\nFor activemodel 3.0 and 3.1, please use file_validators version `\u003c= 2.1`.\n\nIt has been tested to work with Carrierwave, Paperclip, Dragonfly, Refile etc file uploading solutions.\nValidations works both before and after uploads.\n\n## Installation\n\nAdd the following to your Gemfile:\n\n```ruby\ngem 'file_validators'\n```\n\n## Examples\n\nActiveModel example:\n\n```ruby\nclass Profile\n  include ActiveModel::Validations\n\n  attr_accessor :avatar\n  validates :avatar, file_size: { less_than_or_equal_to: 100.kilobytes },\n                     file_content_type: { allow: ['image/jpeg', 'image/png'] }\nend\n```\nActiveRecord example:\n\n```ruby\nclass Profile \u003c ActiveRecord::Base\n  validates :avatar, file_size: { less_than_or_equal_to: 100.kilobytes },\n                     file_content_type: { allow: ['image/jpeg', 'image/png'] }\nend\n```\n\nYou can also use `:validates_file_size` and `:validates_file_content_type` idioms.\n\n## API\n\n### File Size Validator:\n\n* `in`: A range of bytes or a proc that returns a range\n```ruby\nvalidates :avatar, file_size: { in: 100.kilobytes..1.megabyte }\n```\n* `less_than`: Less than a number in bytes or a proc that returns a number\n```ruby\nvalidates :avatar, file_size: { less_than: 2.gigabytes }\n```\n* `less_than_or_equal_to`: Less than or equal to a number in bytes or a proc that returns a number\n```ruby\nvalidates :avatar, file_size: { less_than_or_equal_to: 50.bytes }\n```\n* `greater_than`: greater than a number in bytes or a proc that returns a number\n```ruby\nvalidates :avatar, file_size: { greater_than: 1.byte }\n```\n* `greater_than_or_equal_to`: Greater than or equal to a number in bytes or a proc that returns a number\n```ruby\nvalidates :avatar, file_size: { greater_than_or_equal_to: 50.bytes }\n```\n* `message`: Error message to display. With all the options above except `:in`, you will get `count` as a replacement.\nWith `:in` you will get `min` and `max` as replacements.\n`count`, `min` and `max` each will have its value and unit together.\nYou can write error messages without using any replacement.\n```ruby\nvalidates :avatar, file_size: { less_than: 100.kilobytes,\n                                message: 'avatar should be less than %{count}' }\n```\n```ruby\nvalidates :document, file_size: { in: 1.kilobyte..1.megabyte,\n                                  message: 'must be within %{min} and %{max}' }\n```\n* `if`: A lambda or name of an instance method. Validation will only be run if this lambda or method returns true.\n* `unless`: Same as `if` but validates if lambda or method returns false.\n\nYou can combine different options.\n```ruby\nvalidates :avatar, file_size: { less_than: 1.megabyte,\n                                greater_than_or_equal_to: 20.kilobytes }\n```\nThe following two examples are equivalent:\n```ruby\nvalidates :avatar, file_size: { greater_than_or_equal_to: 500.kilobytes,\n                                less_than_or_equal_to: 3.megabytes }\n```\n```ruby\nvalidates :avatar, file_size: { in: 500.kilobytes..3.megabytes }\n```\nOptions can also take `Proc`/`lambda`:\n\n```ruby\nvalidates :avatar, file_size: { less_than: lambda { |record| record.size_in_bytes } }\n```\n\n### File Content Type Validator\n\n* `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.\n```ruby\n# string\nvalidates :avatar, file_content_type: { allow: 'image/jpeg' }\n```\n```ruby\n# array of strings\nvalidates :attachment, file_content_type: { allow: ['image/jpeg', 'text/plain'] }\n```\n```ruby\n# regexp\nvalidates :avatar, file_content_type: { allow: /^image\\/.*/ }\n```\n```ruby\n# array of regexps\nvalidates :attachment, file_content_type: { allow: [/^image\\/.*/, /^text\\/.*/] }\n```\n```ruby\n# array of regexps and strings\nvalidates :attachment, file_content_type: { allow: [/^image\\/.*/, 'video/mp4'] }\n```\n```ruby\n# proc/lambda example\nvalidates :video, file_content_type: { allow: lambda { |record| record.content_types } }\n```\n* `exclude`: Forbidden content types. Can be a single content type or an array. Each type\ncan be a String or a Regexp. It also accepts `proc`. See `:allow` options examples.\n* `mode`: `:strict` or `:relaxed`. `:strict` mode can detect content type based on the contents\nof the files. It also detects media type spoofing (see more in [security](#security)).\n`:file` analyzer is used in `:strict` mode. `:relaxed` mode uses file name to detect\nthe content type. `mime_types` analyzer is used in `relaxed` mode. If mode option is not\nset then the validator uses form supplied content type.\n* `tool`: `:file`, `:fastimage`, `:filemagic`, `:mimemagic`, `:marcel`, `:mime_types`, `:mini_mime`.\nYou can choose one of these built-in MIME type analyzers. You have to install the analyzer gem you choose.\nBy default supplied content type is used to determine the MIME type. This option takes precedence\nover `mode` option.\n```ruby\nvalidates :avatar, file_content_type: { allow: 'image/jpeg', mode: :strict }\nvalidates :avatar, file_content_type: { allow: 'image/jpeg', mode: :relaxed }\n```\n* `message`: The message to display when the uploaded file has an invalid content type.\nYou will get `types` as a replacement. You can write error messages without using any replacement.\n```ruby\nvalidates :avatar, file_content_type: { allow: ['image/jpeg', 'image/gif'],\n                                        message: 'only %{types} are allowed' }\n```\n```ruby\nvalidates :avatar, file_content_type: { allow: ['image/jpeg', 'image/gif'],\n                                        message: 'Avatar only allows jpeg and gif' }\n```\n* `if`: A lambda or name of an instance method. Validation will only be run is this lambda or method returns true.\n* `unless`: Same as `if` but validates if lambda or method returns false.\n\nYou can combine `:allow` and `:exclude`:\n```ruby\n# this will allow all the image types except png and gif\nvalidates :avatar, file_content_type: { allow: /^image\\/.*/, exclude: ['image/png', 'image/gif'] }\n```\n\n## Security\n\nThis gem can use Unix file command to get the content type based on the content of the file rather\nthan the extension. This prevents fake content types inserted in the request header.\n\nIt also prevents file media type spoofing. For example, user may upload a .html document as\na part of the EXIF header of a valid JPEG file. Content type validator will identify its content type\nas `image/jpeg` and, without spoof detection, it may pass the validation and be saved as .html document\nthus exposing your application to a security vulnerability. Media type spoof detector wont let that happen.\nIt will not allow a file having `image/jpeg` content type to be saved as `text/plain`. It checks only media\ntype mismatch, for example `text` of `text/plain` and `image` of `image/jpeg`. So it will not prevent\n`image/jpeg` from saving as `image/png` as both have the same `image` media type.\n\n**note**: This security feature is disabled by default. To enable it, add `mode: :strict` option\nin [content type validations](#file-content-type-validator).\n`:strict` mode may not work in direct file uploading systems as the file is not passed along with the form.\n\n## i18n Translations\n\nFile Size Errors\n* `file_size_is_in`: takes `min` and `max` as replacements\n* `file_size_is_less_than`: takes `count` as replacement\n* `file_size_is_less_than_or_equal_to`: takes `count` as replacement\n* `file_size_is_greater_than`: takes `count` as replacement\n* `file_size_is_greater_than_or_equal_to`: takes `count` as replacement\n\nContent Type Errors\n* `allowed_file_content_types`: generated when you have specified allowed types but the content type\nof the file doesn't match. takes `types` as replacement.\n* `excluded_file_content_types`: generated when you have specified excluded types and the content type\nof the file matches anyone of them. takes `types` as replacement.\n\nThis gem provides `en` translations for this errors under `errors.messages` namespace.\nIf you want to override and/or create other locales, you can\ncheck [this](https://github.com/musaffa/file_validators/blob/master/lib/file_validators/locale/en.yml) out to see how translations are done.\n\nYou can override all of them with the `:message` option.\n\nFor unit format, it will use `number.human.storage_units.format` from your locale.\nFor unit translation, `number.human.storage_units` is used.\nRails applications already have these translations either in ActiveSupport's locale (Rails 4) or in ActionView's locale (Rails 3).\nIn case your setup doesn't have the translations, here's an example for `en`:\n\n```yml\nen:\n  number:\n    human:\n      storage_units:\n        format: \"%n %u\"\n        units:\n          byte:\n            one:   \"Byte\"\n            other: \"Bytes\"\n          kb: \"KB\"\n          mb: \"MB\"\n          gb: \"GB\"\n          tb: \"TB\"\n```\n\n## Further Instructions\n\nIf you are using `:strict` or `:relaxed` mode, for content types which are not supported\nby mime-types gem, you need to register those content types. For example, you can register\n`.docx` in the initializer:\n```Ruby\n# config/initializers/mime_types.rb\nMime::Type.register \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\", :docx\n```\n\nIf you want to see what content type `:strict` mode returns, run this command in the shell:\n```Shell\n$ file -b --mime-type your-file.xxx\n```\n\n## Issues\n\n**Carrierwave** - You are adding file validators to a model, then you are recommended to keep extension_white_list \u0026/\nextension_black_list in the uploaders (in case you don't have, add that method).\nAs of this writing (see [issue](https://github.com/carrierwaveuploader/carrierwave/issues/361)), Carrierwave\nuploaders start processing a file immediately after its assignment (even before the validators are called).\n\n## Tests\n\n```Shell\n$ rake\n$ rake test:unit\n$ rake test:integration\n$ rubocop\n\n# test different active model versions\n$ bundle exec appraisal install\n$ bundle exec appraisal rake\n```\n\n## Problems\n\nPlease use GitHub's [issue tracker](http://github.com/musaffa/file_validations/issues).\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Added some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n\n## Inspirations\n\n* [PaperClip](https://github.com/thoughtbot/paperclip)\n\n## License\n\nThis project rocks and uses MIT-LICENSE.\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmusaffa%2Ffile_validators","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmusaffa%2Ffile_validators","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmusaffa%2Ffile_validators/lists"}