diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 44529a9b2..79e48b807 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -66,14 +66,12 @@ def update end def update_avatar - avatar = params[:avatar] - errors = validate_avatar(avatar) + operation = AvatarGenerator.new(current_user, params) - if errors.blank? - current_user.avatar.purge if current_user.avatar.attached? - crop_image_and_save(current_user, avatar) + if operation.errors.empty? + operation.call else - flash[:error] = errors.join("
") + flash[:error] = operation.errors.join("
") end redirect_to current_user @@ -130,38 +128,4 @@ def redirect_to_after_create name: @user.username) end end - - def crop_image_and_save(user, avatar) - orig_width = params[:original_width].to_i - width = params[:height_width].to_i - left = params[:width_offset].to_i - top = params[:height_offset].to_i - - image_processed = ImageProcessing::MiniMagick. - source(avatar.tempfile). - resize_to_fit(orig_width, nil). - crop("#{width}x#{width}+#{left}+#{top}!"). - convert("png"). - call - - user.avatar.attach( - io: image_processed, - filename: user.username, - content_type: avatar.content_type - ) - end - - def validate_avatar(file) - errors = [] - - if User::AVATAR_CONTENT_TYPES.exclude?(file.content_type) - errors << t("users.show.invalid_format") - end - - if file.size.to_f > User::AVATAR_MAX_SIZE.megabytes - errors << t("users.avatar.max_size_warning", size: User::AVATAR_MAX_SIZE) - end - - errors - end end diff --git a/app/models/user.rb b/app/models/user.rb index a0eb4bc9a..4f3e006c8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -9,8 +9,6 @@ class User < ApplicationRecord :timeoutable ] - AVATAR_MAX_SIZE = 5 - AVATAR_CONTENT_TYPES = %w[image/jpeg image/pjpeg image/png image/x-png] GENDERS = %w( female male diff --git a/app/services/avatar_generator.rb b/app/services/avatar_generator.rb new file mode 100644 index 000000000..d04187f4c --- /dev/null +++ b/app/services/avatar_generator.rb @@ -0,0 +1,51 @@ +class AvatarGenerator + MAX_SIZE = 5 + CONTENT_TYPES = %w[image/jpeg image/pjpeg image/png image/x-png] + + attr_accessor :errors + + def initialize(user, params) + @user = user + @params = params + @avatar = params[:avatar] + @errors = [] + + validate_avatar + end + + def call + @user.avatar.purge if @user.avatar.attached? + + @user.avatar.attach( + io: process_image, + filename: @user.username, + content_type: @avatar.content_type + ) + end + + private + + def process_image + orig_width = @params[:original_width].to_i + width = @params[:height_width].to_i + left = @params[:width_offset].to_i + top = @params[:height_offset].to_i + + ImageProcessing::MiniMagick. + source(@avatar.tempfile). + resize_to_fit(orig_width, nil). + crop("#{width}x#{width}+#{left}+#{top}!"). + convert("png"). + call + end + + def validate_avatar + if CONTENT_TYPES.exclude?(@avatar.content_type) + @errors << I18n.t("users.show.invalid_format") + end + + if @avatar.size.to_f > MAX_SIZE.megabytes + @errors << I18n.t("users.avatar.max_size_warning", size: MAX_SIZE) + end + end +end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index aac98519f..16676d9fb 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -433,7 +433,7 @@ end it "don't change the photo attached if the file size it too big" do - allow_any_instance_of(ActionDispatch::Http::UploadedFile).to receive(:size) { User::AVATAR_MAX_SIZE.megabytes + 1.megabyte } + allow_any_instance_of(ActionDispatch::Http::UploadedFile).to receive(:size) { AvatarGenerator::MAX_SIZE.megabytes + 1.megabyte } put :update_avatar, params: { avatar: uploaded_file }