Last active
August 20, 2020 09:12
-
-
Save absk1317/9634e0008d7ed099209a7d7093aaf384 to your computer and use it in GitHub Desktop.
Async Image Processing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
# == Schema Information | |
# | |
# Table name: images | |
# | |
# id :bigint not null, primary key | |
# deleted_at :datetime indexed | |
# height :decimal(, ) | |
# image :string | |
# temp_image :string not null | |
# width :decimal(, ) | |
# created_at :datetime not null | |
# updated_at :datetime not null | |
# | |
# Indexes | |
# | |
# index_images_on_deleted_at (deleted_at) | |
# | |
# Image ORM | |
class Image < ApplicationRecord | |
include RailsAdmin::Image | |
acts_as_paranoid | |
MAX_ALLOWED_FILE_SIZE = 14 | |
mount_uploader :temp_image, TempImageUploader | |
mount_uploader :image, ImageUploader | |
has_many :image_uploads, dependent: :destroy | |
after_commit :create_versions, on: :create | |
validate :temp_image_presence, :file_size | |
validate :image_dimensions, on: :create | |
attr_accessor :creation_token | |
def url | |
image&.url || temp_image.url | |
end | |
alias original_image_url url | |
alias upload_id id | |
%w[logo medium onesignal].each do |version_type| | |
define_method "#{version_type}_version_url" do | |
return temp_image.url unless image&.send(version_type)&.url | |
image.send(version_type).url | |
end | |
end | |
def image_json | |
{ upload_id: id, | |
original_image_url: url, | |
medium_version_url: medium_version_url, | |
logo_version_url: logo_version_url, | |
width: width.to_i, | |
height: height.to_i } | |
end | |
def file_size | |
upload_limit = MAX_ALLOWED_FILE_SIZE.to_f | |
return unless temp_image.file&.size.to_f / (1000 * 1000) > upload_limit | |
errors.add(:image, I18n.t('images.errors.size', upload_limit: upload_limit)) | |
end | |
def create_versions | |
::ImageProcessingWorker.perform_async(id) | |
end | |
def temp_image_presence | |
# didn't use validates :temp_image, presence: true because wanted to add error to image, not temp image | |
errors.add(:image, "can't be blank") unless temp_image.present? | |
end | |
def image_dimensions | |
return if admin_edit.to_s == '1' | |
return if width.to_i > 120 && height.to_i > 120 | |
errors.add(:image, I18n.t('images.errors.dimensions')) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
class ImageProcessingWorker | |
include Sidekiq::Worker | |
sidekiq_options queue: 'default', retry: 10 | |
def perform(upload_id) | |
object = Image.find(upload_id) | |
return if object.image.present? | |
object.image = object.temp_image | |
object.save | |
## use sidekiq backoff instead of managing manaully. Wouldn't be triggered in most of the times. | |
raise ActiveRecord::RecordInvalid unless object.image.present? | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
require 'rails_helper' | |
describe ImageProcessingWorker do | |
it 'updates image column with temp image column' do | |
Sidekiq::Testing.inline! | |
image = Image.create!(temp_image: fixture_file_upload('test_image.jpg', 'image/jpg')) | |
expect(image.image.present?).to eq(false) | |
expect(image.temp_image.present?).to eq(true) | |
ImageProcessingWorker.perform_async(image.id) | |
expect(image.reload.image.present?).to eq(true) # adds the image | |
expect(image.reload.temp_image.present?).to eq(true) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment