Как загрузить при изменении размера самого исходного изображения в Shrine

Я использую Shrine в приложении Ruby on Rails для создания процесса изменения размера и загрузки изображений в хранилище.

Мой текущий код:


image_uploader.rb

require "image_processing/mini_magick"

class ImageUploader < Shrine
  plugin :derivatives

  Attacher.derivatives_processor do |original|
    magick = ImageProcessing::MiniMagick.source(original)
    {
      resized: magick.resize_to_limit!(120, 120)
    }
  end

end

user.rb

class User < ApplicationRecord
  include ImageUploader::Attachment(:image)
  before_save :image_resize

  def image_resize
    self.image_derivatives!
  end
end

Я реализовал это при чтении официальной документации, но это нежелательно по двум причинам.

  1. Требуется триггер в коде модели. Можно ли его дополнить только image_uploader.rb?
  2. Для доступа к изображениям, созданным с помощью этого кода, требуется префикс «измененного размера» (например, @user.image(:resized).url), и исходное изображение также останется в хранилище. Я хочу обработать исходное изображение.

Есть ли способ загрузки при решении этих двух проблем?


person sink66    schedule 24.11.2019    source источник


Ответы (1)


  1. Вы можете добавить следующий патч, который будет запускать создание производных в рамках продвижения кэшированного файла в постоянное хранилище:

    # put this in your initializer
    class Shrine::Attacher
      def promote(*)
        create_derivatives
        super
      end
    end
    
  2. Вы можете просто переопределить метод модели, который извлекает прикрепленный файл, чтобы вернуть версию с измененным размером. Вы можете использовать плагин included, чтобы сделать это для всех моделей, использующих этот загрузчик:

    class ImageUploader < Shrine
      # ...
      plugin :included do |name|
        define_method(name) { super(:resized) }
      end
    end
    

Что касается второго вопроса: он по-прежнему сохранит исходный файл в хранилище, но вместо этого по умолчанию просто вернет версию с измененным размером. Как правило, лучше делать это в декораторе представления.

Вы всегда хотите сохранить исходный файл в хранилище, потому что никогда не знаете, когда вам понадобится его повторно обработать. Может случиться так, что вы обнаружите, что ваша текущая логика изменения размера не идеальна для определенных типов и размеров файлов, и в этом случае вам потребуется повторно создать версию с измененным размером для предыдущих вложений. И вы не смогли бы этого сделать, если бы у вас больше не было исходного файла.

person janko-m    schedule 24.11.2019
comment
Q 1 : Это сработало! Q 2: Мое приложение хочет установить размер изображения 120x120 и не будет повторно обрабатывать его позже. Так что нет необходимости сохранять другие размеры. В этом случае, например, carrierwave, похоже, может изменить размер исходного изображения. сам с process resize_to_fit. Мое использование может не соответствовать Shrine ... Спасибо за ответ. - person sink66; 25.11.2019
comment
+1 за хранение оригинального файла. Алгоритмы улучшаются, как и методы кодирования изображений, которые позволяют нам уменьшать размер хранилища или улучшать качество визуализированного изображения, а наличие оригинала позволяет использовать их в других новых и интересных целях. - person the Tin Man; 25.11.2019
comment
Я согласен с тем, что лучше всего хранить исходный файл, но я также считаю, что должен быть способ легко переопределить это в Shrine. Иногда вы действительно не заботитесь об оригинале и из-за недостатка места не хотите его хранить. - person andyrue; 12.02.2020
comment
Я буду иметь это в виду и, возможно, добавлю эту способность в будущем. На данный момент в этом обсуждении есть несколько предложений о том, как этого добиться с помощью текущего API. - person janko-m; 12.02.2020