Не удается получить метаданные Shrine - PullRequest
0 голосов
/ 25 февраля 2019

Я переключаюсь с Paperclip на Shrine из-за устаревания Paperclip.

В файле моей модели Profilepic.rb я использовал для получения размеров варианта изображения следующим образом:

before_create  :save_ratio    

def save_ratio
    geo = Paperclip::Geometry.from_file(image.queued_for_write[:original])
    self.ratio = geo.width / geo.height
  end

В основномЯ сохраняю вертикальное соотношение изображения.

С Paperclip все работало хорошо: я взял временное изображение queued_for_write и проверил размеры с помощью Paperclip::Geometry перед сохранением значения.

В Shrine я добавил следующее к загрузчику:

plugin :add_metadata
plugin :store_dimensions

Это прекрасно работает, так как у меня есть вся доступная информация и изображения загружаются на S3 должным образом.

Тем не менее, мой новый метод сохранения соотношения изображений больше не работает:

after_create  :save_ratio
def save_ratio
    self.ratio = self.image[:original].width.to_i / self.image[:original].height.to_i
  end

Я получаю

Ошибка неопределенного метода `[] 'для ProfilepicUploader ::UploadedFile: 0x00007f69a685c750>

Принимая во внимание, что в консоли после создания изображения:

Profilepic.first.image[:original].width.to_i

возвращает правильное значение.

EDIT

Мой загрузчик:

require "image_processing/mini_magick"

class ProfilepicUploader < Shrine
    include ImageProcessing::MiniMagick
    plugin :processing
    plugin :validation_helpers # to validate image data
    plugin :versions
    plugin :add_metadata
    plugin :store_dimensions

    Attacher.validate do
        validate_max_size 5.megabyte
        validate_mime_type_inclusion ['image/jpg', 'image/jpeg', 'image/png']
    end

    process(:store) do |io, context|
        versions = { original: io } # retain original

        io.download do |original|
            pipeline = ImageProcessing::MiniMagick.source(original)

            versions[:editable]  = pipeline.resize_to_fit!(700, 700)
            versions[:thumbnail] = pipeline.resize_to_fill!(400, 400)
            versions[:small]  = pipeline.resize_to_fill!(200, 200)
        end

        versions # return the hash of processed files
    end

end

моя модель:

class Profilepic < ApplicationRecord
  require "image_processing/mini_magick"
  belongs_to :professionnel
  before_create :set_hashid

  include ProfilepicUploader::Attachment.new(:image) # adds an `image` virtual attribute
  include ProfilepicFinalUploader::Attachment.new(:final_image) # adds an `image` virtual attribute


 attr_accessor :crop_x, :crop_y, :crop_w, :crop_h   

 after_create  :save_ratio_image   

private

  def save_ratio
    self.ratio = self.image[:original].width.to_i / self.image[:original].height.to_i
  end

end

Ответы [ 2 ]

0 голосов
/ 26 февраля 2019

Храм сначала сохраняет запись в кэшированном файле, а затем снова в сохраненных обработанных файлах.Причина, по которой вы получаете сообщение об ошибке, заключается в том, что ваш код сначала запускается при назначении кэшированного файла, и в этот момент обработка еще не была выполнена, а self.image представляет собой один загруженный файл (не хэш загруженных файлов)..

Что вам, вероятно, нужно, - это извлечь соотношение уже из файла , кэшированного (который является тем же загруженным файлом, что и :original после обработки):

def save_ratio
  if image_data_changed? && image_attacher.cached?
    self.ratio = image.width.to_f / image.height.to_f
  end
end

В качестве альтернативы, вы можете создать столбцы image_width и image_height, и Shrine автоматически заполнит их метаданными width & height, а затем вычислит соотношение позже в SQL.

class ProfilepicUploader < Shrine
  plugin :metadata_attributes, width: :width, height: height
end

Как упоминалось вВ комментариях к другому ответу вы также можете использовать столбец JSONB для столбца вложения, который также позволяет извлекать метаданные width & height с помощью SQL.

0 голосов
/ 25 февраля 2019

мои 2 цента:

Если вы используете Shrine :: Attach.promote для обработки файлов в фоновом режиме, через задание или работника, и метаданные versions могут быть недоступны в это время (after_createвремя обратного вызова).

Я не уверен, что лучший способ решить эту проблему, но вы можете получить доступ к модели на этапе обработки через контекст (https://github.com/shrinerb/shrine/blob/v2.16.0/doc/processing.md#processing-on-upload):

class SomeUploader < Shrine
  process(:store) do |io, context|
    ratio = io.metadata["width"] / io.metadata["height"]
    model = context[:record]
    model.update(ratio: ratio)

    versions = { original: io } # retain original
    io.download do |original|
      pipeline = ImageProcessing::MiniMagick.source(original)
      versions[:small]  = pipeline.resize_to_limit!(300, 300)
      # ....
    end
    versions
  end
end
...