1
0
Fork 0

Add ImageValidator

This commit is contained in:
Alex Kotov 2019-03-25 08:04:53 +05:00
parent 25a06b1ce1
commit da7d84ba51
Signed by: kotovalexarian
GPG key ID: 553C0EBBEB5D5F08
7 changed files with 85 additions and 36 deletions

View file

@ -6,14 +6,6 @@ class Account < ApplicationRecord
NICKNAME_RE = /\A[a-z][_a-z0-9]*[a-z0-9]\z/.freeze NICKNAME_RE = /\A[a-z][_a-z0-9]*[a-z0-9]\z/.freeze
AVATAR_MAX_SIZE = 1.megabyte
AVATAR_CONTENT_TYPES = %w[
image/png
image/jpeg
image/gif
].freeze
self.role_cname = 'Role' self.role_cname = 'Role'
self.role_table_name = 'roles' self.role_table_name = 'roles'
self.strict_rolify = false self.strict_rolify = false
@ -76,8 +68,7 @@ class Account < ApplicationRecord
validates :biography, allow_nil: true, length: { in: 3..10_000 } validates :biography, allow_nil: true, length: { in: 3..10_000 }
validate :avatar_size_is_valid validates :avatar, allow_nil: true, image: true
validate :avatar_content_type_is_valid
########### ###########
# Methods # # Methods #
@ -137,18 +128,4 @@ private
self.public_name = public_name&.strip self.public_name = public_name&.strip
self.biography = biography&.strip self.biography = biography&.strip
end end
def avatar_size_is_valid
return unless avatar.attached?
return if avatar.blob.byte_size <= AVATAR_MAX_SIZE
errors.add :avatar, :size
end
def avatar_content_type_is_valid
return unless avatar.attached?
return if avatar.blob.content_type.in? AVATAR_CONTENT_TYPES
errors.add :avatar, :format, content_type: avatar.blob.content_type
end
end end

View file

@ -0,0 +1,39 @@
# frozen_string_literal: true
class ApplicationEachValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
self.class::Validation.new(self, record, attribute, value).call
end
class Validation
attr_reader :value
delegate :options, to: :@validator
def initialize(validator, record, attribute, value)
@validator = validator
@record = record
@attribute = attribute
@value = value
end
def call
catch :stop_validating do
perform
end
end
def perform
raise NotImplementedError, "#{self.class}#perform"
end
def error(*args)
@record.errors.add @attribute, *args
end
def error!(*args)
error(*args)
throw :stop_validating
end
end
end

View file

@ -0,0 +1,27 @@
# frozen_string_literal: true
class ImageValidator < ApplicationEachValidator
class Validation < Validation
MAX_SIZE = 1.megabyte
CONTENT_TYPES = %w[
image/png
image/jpeg
image/gif
].freeze
delegate :blob, to: :value
delegate :content_type, :byte_size, to: :blob
def perform
return unless value.attached?
unless content_type.in? CONTENT_TYPES
error :image_format, content_type: content_type
end
error :image_size unless byte_size <= MAX_SIZE
end
end
end

View file

@ -41,6 +41,11 @@ module Partynest
# Fully qualified domain name. # Fully qualified domain name.
config.site_domain = 'libertarian-party.com' config.site_domain = 'libertarian-party.com'
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += [
config.root.join('app', 'validators'),
]
# Email which all mail is set from. # Email which all mail is set from.
config.noreply_email_address = "no-reply@#{config.site_domain}" config.noreply_email_address = "no-reply@#{config.site_domain}"
config.noreply_email_contact = config.noreply_email_contact =

View file

@ -108,9 +108,6 @@ en:
unlock_token: Unlock token unlock_token: Unlock token
updated_at: Updated at updated_at: Updated at
errors: errors:
models: messages:
account: image_size: 'has too big size'
attributes: image_format: 'has invalid format: %{content_type}'
avatar:
size: 'has too big size'
format: 'has invalid format: %{content_type}'

View file

@ -108,9 +108,6 @@ ru:
unlock_token: Токен разблокировки unlock_token: Токен разблокировки
updated_at: Дата обновления updated_at: Дата обновления
errors: errors:
models: messages:
account: image_size: 'имеет слишком большой размер'
attributes: image_format: 'имеет неверный формат: %{content_type}'
avatar:
size: 'имеет слишком большой размер'
format: 'имеет неверный формат: %{content_type}'

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe ImageValidator do
pending "add some examples to (or delete) #{__FILE__}"
end