All Projects → igorkasyanchuk → Active_storage_validations

igorkasyanchuk / Active_storage_validations

Licence: mit
Do it like => validates :photos, attached: true, content_type: ['image/png', 'image/jpg', 'image/jpeg'], size: { less_than: 500.kilobytes }, limit: { min: 1, max: 3 }, aspect_ratio: :landscape, dimension: { width: { in: 800..1600 }

Programming Languages

ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to Active storage validations

Html5 validators
A gem/plugin for Rails 3, Rails 4, Rails 5, and Rails 6 that enables client-side validation using ActiveModel + HTML5 Form Validation
Stars: ✭ 302 (-42.15%)
Mutual labels:  validations, rails
Graphql Ruby
Ruby implementation of GraphQL
Stars: ✭ 4,931 (+844.64%)
Mutual labels:  rails
Sorbet Rails
A set of tools to make the Sorbet typechecker work with Ruby on Rails seamlessly.
Stars: ✭ 464 (-11.11%)
Mutual labels:  rails
Motion
Reactive frontend UI components for Rails in pure Ruby
Stars: ✭ 498 (-4.6%)
Mutual labels:  rails
Matestack Ui Core
Matestack enables you to create sophisticated, reactive UIs in pure Ruby, without touching JavaScript and HTML. You end up writing 50% less code while increasing productivity, maintainability and developer happiness.
Stars: ✭ 469 (-10.15%)
Mutual labels:  rails
Acts as api
makes creating API responses in Rails easy and fun
Stars: ✭ 506 (-3.07%)
Mutual labels:  rails
Rails5 api tutorial
Learn how to build a modern API on Michael Hartl's Rails 5 tutorial
Stars: ✭ 458 (-12.26%)
Mutual labels:  rails
Ajax Datatables Rails
A wrapper around DataTable's ajax methods that allow synchronization with server-side pagination in a Rails app
Stars: ✭ 520 (-0.38%)
Mutual labels:  rails
Zero downtime migrations
Zero downtime migrations with ActiveRecord 3+ and PostgreSQL
Stars: ✭ 513 (-1.72%)
Mutual labels:  rails
Sail
Sail is a lightweight Rails engine that brings an admin panel for managing configuration settings on a live Rails app
Stars: ✭ 484 (-7.28%)
Mutual labels:  rails
Stealth
An open source Ruby framework for text and voice chatbots. 🤖
Stars: ✭ 481 (-7.85%)
Mutual labels:  rails
Attribute normalizer
Adds the ability to normalize attributes cleanly with code blocks and predefined normalizers
Stars: ✭ 473 (-9.39%)
Mutual labels:  rails
Inline svg
Embed SVG documents in your Rails views and style them with CSS
Stars: ✭ 510 (-2.3%)
Mutual labels:  rails
Godmin
Admin framework for Rails 4+
Stars: ✭ 464 (-11.11%)
Mutual labels:  rails
Letter opener web
A web interface for browsing Ruby on Rails sent emails
Stars: ✭ 513 (-1.72%)
Mutual labels:  rails
Hyperstack
Hyperstack ALPHA https://hyperstack.org
Stars: ✭ 463 (-11.3%)
Mutual labels:  rails
Opal Rails
Bringing Ruby to Rails · Rails bindings for Opal
Stars: ✭ 477 (-8.62%)
Mutual labels:  rails
Maily
📫 Rails Engine to preview emails in the browser
Stars: ✭ 502 (-3.83%)
Mutual labels:  rails
Fuzzapi
Fuzzapi is a tool used for REST API pentesting and uses API_Fuzzer gem
Stars: ✭ 521 (-0.19%)
Mutual labels:  rails
Terraforming Rails
Terraforming legacy Rails applications guides and tools
Stars: ✭ 517 (-0.96%)
Mutual labels:  rails

Active Storage Validations

MiniTest RailsJazz

If you are using active_storage gem and you want to add simple validations for it, like presence or content_type you need to write a custom validation method.

This gems doing it for you. Just use attached: true or content_type: 'image/png' validation.

What it can do

  • validates if file(s) attached
  • validates content type
  • validates size of files
  • validates dimension of images/videos
  • validates number of uploaded files (min/max required)
  • validates aspect ratio (if square, portrait, landscape, is_16_9, ...)
  • custom error messages

Usage

For example you have a model like this and you want to add validation.

class User < ApplicationRecord
  has_one_attached :avatar
  has_many_attached :photos

  validates :name, presence: true

  validates :avatar, attached: true, content_type: 'image/png',
                                     dimension: { width: 200, height: 200 }
  validates :photos, attached: true, content_type: ['image/png', 'image/jpg', 'image/jpeg'],
                                     dimension: { width: { min: 800, max: 2400 },
                                                  height: { min: 600, max: 1800 }, message: 'is not given between dimension' }
  validates :image, attached: true,
                    content_type: ['image/png', 'image/jpg'],
                    aspect_ratio: :landscape
end

or

class Project < ApplicationRecord
  has_one_attached :preview
  has_one_attached :attachment
  has_many_attached :documents

  validates :title, presence: true

  validates :preview, attached: true, size: { less_than: 100.megabytes , message: 'is not given between size' }
  validates :attachment, attached: true, content_type: { in: 'application/pdf', message: 'is not a PDF' }
  validates :documents, limit: { min: 1, max: 3 }
end

More examples

  • Content type validation using symbols. In order to infer the correct mime type from the symbol, the types must be registered with Mime::Type.
class User < ApplicationRecord
  has_one_attached :avatar
  has_many_attached :photos

  validates :avatar, attached: true, content_type: :png # Mime[:png].to_s => 'image/png'
  # or
  validates :photos, attached: true, content_type: [:png, :jpg, :jpeg]
  # or
  validates :avatar, content_type: /\Aimage\/.*\z/
end
  • Dimension validation with width, height and in.
class User < ApplicationRecord
  has_one_attached :avatar
  has_many_attached :photos

  validates :avatar, dimension: { width: { in: 80..100 }, message: 'is not given between dimension' }
  validates :photos, dimension: { height: { in: 600..1800 } }
end
  • Dimension validation with min and max range for width and height:
class User < ApplicationRecord
  has_one_attached :avatar
  has_many_attached :photos

  validates :avatar, dimension: { min: 200..100 }
  # Equivalent to:
  # validates :avatar, dimension: { width: { min: 200 }, height: { min: 100  } }
  validates :photos, dimension: { min: 200..100, max: 400..200 }
  # Equivalent to:
  # validates :avatar, dimension: { width: { min: 200, max: 400 }, height: { min: 100, max: 200  } }
end
  • Aspect ratio validation:
class User < ApplicationRecord
  has_one_attached :avatar
  has_one_attached :photo
  has_many_attached :photos

  validates :avatar, aspect_ratio: :square
  validates :photo, aspect_ratio: :landscape

  # you can also pass dynamic aspect ratio, like :is_4_3, :is_16_9, etc
  validates :photos, aspect_ratio: :is_4_3
end

Internationalization (I18n)

Active Storage Validations uses I18n for error messages. For this, add these keys in your translation file:

en:
  errors:
    messages:
      content_type_invalid: "has an invalid content type"
      file_size_out_of_range: "size %{file_size} is not between required range"
      limit_out_of_range: "total number is out of range"
      image_metadata_missing: "is not a valid image"
      dimension_min_inclusion: "must be greater than or equal to %{width} x %{height} pixel."
      dimension_max_inclusion: "must be less than or equal to %{width} x %{height} pixel."
      dimension_width_inclusion: "width is not included between %{min} and %{max} pixel."
      dimension_height_inclusion: "height is not included between %{min} and %{max} pixel."
      dimension_width_greater_than_or_equal_to: "width must be greater than or equal to %{length} pixel."
      dimension_height_greater_than_or_equal_to: "height must be greater than or equal to %{length} pixel."
      dimension_width_less_than_or_equal_to: "width must be less than or equal to %{length} pixel."
      dimension_height_less_than_or_equal_to: "height must be less than or equal to %{length} pixel."
      dimension_width_equal_to: "width must be equal to %{length} pixel."
      dimension_height_equal_to: "height must be equal to %{length} pixel."
      aspect_ratio_not_square: "must be a square image"
      aspect_ratio_not_portrait: "must be a portrait image"
      aspect_ratio_not_landscape: "must be a landscape image"
      aspect_ratio_is_not: "must have an aspect ratio of %{aspect_ratio}"
      aspect_ratio_unknown: "has an unknown aspect ratio"

In some cases, Active Storage Validations provides variables to help you customize messages:

The "content_type_invalid" key has two variables that you can use, a variable named "content_type" containing the content type of the send file and a variable named "authorized_types" containing the list of authorized content types.

The variables are not used by default to leave the choice to the user.

For example :

content_type_invalid: "has an invalid content type : %{content_type}"

Also the "limit_out_of_range" key supports two variables the "min" and "max".

For example :

limit_out_of_range: "total number is out of range. range: [%{min}, %{max}]"

Installation

Add this line to your application's Gemfile:

# Rails 5.2 and Rails 6
gem 'active_storage_validations'

# Optional, to use :dimension validator or :aspect_ratio validator
gem 'mini_magick', '>= 4.9.5'

And then execute:

$ bundle

Sample

Very simple example of validation with file attached, content type check and custom error message.

Sample

Test matchers

Provides RSpec-compatible and Minitest-compatible matchers for testing the validators.

RSpec

In spec_helper.rb, you'll need to require the matchers:

require 'active_storage_validations/matchers'

And include the module:

RSpec.configure do |config|
  config.include ActiveStorageValidations::Matchers
end

Example (Note that the options are chainable):

describe User do
  it { is_expected.to validate_attached_of(:avatar) }

  it { is_expected.to validate_content_type_of(:avatar).allowing('image/png', 'image/gif') }
  it { is_expected.to validate_content_type_of(:avatar).rejecting('text/plain', 'text/xml') }

  it { is_expected.to validate_dimensions_of(:avatar).width(250) }
  it { is_expected.to validate_dimensions_of(:avatar).height(200) }
  it { is_expected.to validate_dimensions_of(:avatar).width_min(200) }
  it { is_expected.to validate_dimensions_of(:avatar).width_max(500) }
  it { is_expected.to validate_dimensions_of(:avatar).height_min(100) }
  it { is_expected.to validate_dimensions_of(:avatar).height_max(300) }
  it { is_expected.to validate_dimensions_of(:avatar).width_between(200..500) }
  it { is_expected.to validate_dimensions_of(:avatar).height_between(100..300) }

  it { is_expected.to validate_size_of(:avatar).less_than(50.kilobytes) }
  it { is_expected.to validate_size_of(:avatar).less_than_or_equal_to(50.kilobytes) }
  it { is_expected.to validate_size_of(:avatar).greater_than(1.kilobyte) }
  it { is_expected.to validate_size_of(:avatar).greater_than_or_equal_to(1.kilobyte) }
  it { is_expected.to validate_size_of(:avatar).between(100..500.kilobytes) }
end

Minitest

To use the following syntax, make sure you have the shoulda-context gem up and running. To make use of the matchers you need to require the matchers:

require 'active_storage_validations/matchers'

And extend the module:

class ActiveSupport::TestCase
  extend ActiveStorageValidations::Matchers
end

Example (Note that the options are chainable):

class UserTest < ActiveSupport::TestCase
  should validate_attached_of(:avatar)

  should validate_content_type_of(:avatar).allowing('image/png', 'image/gif')
  should validate_content_type_of(:avatar).rejecting('text/plain', 'text/xml')

  should validate_dimensions_of(:avatar).width(250)
  should validate_dimensions_of(:avatar).height(200)
  should validate_dimensions_of(:avatar).width_min(200)
  should validate_dimensions_of(:avatar).width_max(500)
  should validate_dimensions_of(:avatar).height_min(100)
  should validate_dimensions_of(:avatar).height_max(300)
  should validate_dimensions_of(:avatar).width_between(200..500)
  should validate_dimensions_of(:avatar).height_between(100..300)

  should validate_size_of(:avatar).less_than(50.kilobytes)
  should validate_size_of(:avatar).less_than_or_equal_to(50.kilobytes)
  should validate_size_of(:avatar).greater_than(1.kilobyte)
  should validate_size_of(:avatar).greater_than_or_equal_to(1.kilobyte)
  should validate_size_of(:avatar).between(100..500.kilobytes)
end

Todo

  • verify with remote storages (s3, etc)
  • verify how it works with direct upload
  • better error message when content_size is invalid
  • add more translations

Tests & Contributing

To run tests in root folder of gem:

  • BUNDLE_GEMFILE=gemfiles/rails_5_2.gemfile bundle exec rake test to run for Rails 5.2
  • BUNDLE_GEMFILE=gemfiles/rails_6_0.gemfile bundle exec rake test to run for Rails 6.0
  • BUNDLE_GEMFILE=gemfiles/rails_6_1.gemfile bundle exec rake test to run for Rails 6.1

Known issues

  • There is an issue in Rails which it possible to get if you have added a validation and generating for example an image preview of attachments. It can be fixed with this:
  <% if @user.avatar.attached? && @user.avatar.attachment.blob.present? && @user.avatar.attachment.blob.persisted? %>
    <%= image_tag @user.avatar %>
  <% end %>

This is a Rails issue, and is fixed in Rails 6.

Contributing

You are welcome to contribute.

Contributors (BIG THANK YOU)

License

The gem is available as open source under the terms of the MIT License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].