How to upgrade from versions plugin to derivatives?

207 views
Skip to first unread message

a...@abevoelker.com

unread,
Dec 16, 2019, 4:47:16 PM12/16/19
to Shrine
Hello,

I got the deprecation warning in the latest Shrine version telling me to change from using the "versions" plugin to using "derivatives". I have an uploader in a Rails app that looks like this:

require "image_processing/mini_magick"

class UserAvatarUploader < Shrine
plugin :default_storage,
cache: :user_avatar_cache,
store: :user_avatar_store
plugin :processing
plugin :versions
plugin :store_dimensions
plugin :remote_url, max_size: 20*1024*1024 # 20MB
plugin :delete_raw
plugin :validation_helpers
plugin :determine_mime_type

Attacher.validate do
validate_min_size 1, message: "must not be empty"
validate_max_size 5*1024*1024, message: "is too large (max is 5 MB)"
validate_mime_type_inclusion %w[image/jpeg image/png]
end

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

# download the uploaded file from the temporary storage
io.download do |original|
pipeline = ImageProcessing::MiniMagick.source(original)

versions[:"50"] = pipeline.resize_to_fill!(50, 50, gravity: "Center")
versions[:"100"] = pipeline.resize_to_fill!(100, 100, gravity: "Center")
versions[:"200"] = pipeline.resize_to_fill!(200, 200, gravity: "Center")
versions[:"400"] = pipeline.resize_to_fill!(400, 400, gravity: "Center")
end

versions
end
end


Here's the Rails model that uses it:

class User < ApplicationRecord
include UserAvatarUploader::Attachment(:avatar)
# ...
end


I modified the uploader to use derivatives like so:

require "image_processing/mini_magick"

class UserAvatarUploader < Shrine
plugin :default_storage,
cache: :user_avatar_cache,
store: :user_avatar_store
plugin :store_dimensions
plugin :remote_url, max_size: 20*1024*1024 # 20MB
plugin :validation_helpers
plugin :determine_mime_type
plugin :derivatives

Attacher.validate do
validate_min_size 1, message: "must not be empty"
validate_max_size 5*1024*1024, message: "is too large (max is 5 MB)"
validate_mime_type_inclusion %w[image/jpeg image/png]
end

Attacher.derivatives do |original|
magick = ImageProcessing::MiniMagick.source(original)
{
:"50" => magick.resize_to_fill!( 50, 50, gravity: "Center"),
:"100" => magick.resize_to_fill!(100, 100, gravity: "Center"),
:"200" => magick.resize_to_fill!(200, 200, gravity: "Center"),
:"400" => magick.resize_to_fill!(400, 400, gravity: "Center"),
}
end
end



However when I try to load the attacher on the Rails model, it says "isn't valid uploaded file data"

irb(main):010:0> User.last.avatar
Traceback (most recent call last):
        1: from (irb):10
Shrine::Error ({"50"=>{"id"=>"47f058aa5bb221865ecbc174e9ea8a43.jpg", "storage"=>"user_avatar_store", "metadata"=>{"size"=>1506, "width"=>50, "height"=>50, "filename"=>"image_processing20190805-29116-70z2zj.jpg", "mime_type"=>"image/jpeg"}}, "100"=>{"id"=>"a1ce120dd1ce311f8c7ccaefd6aeab02.jpg", "storage"=>"user_avatar_store", "metadata"=>{"size"=>3032, "width"=>100, "height"=>100, "filename"=>"image_processing20190805-29116-1cwlcfc.jpg", "mime_type"=>"image/jpeg"}}, "200"=>{"id"=>"f169756c5b77a5c2fb496a9cad9e48d7.jpg", "storage"=>"user_avatar_store", "metadata"=>{"size"=>5965, "width"=>200, "height"=>200, "filename"=>"image_processing20190805-29116-hvmc56.jpg", "mime_type"=>"image/jpeg"}}, "400"=>{"id"=>"4db360b3aec63452b382881c603a37e5.jpg", "storage"=>"user_avatar_store", "metadata"=>{"size"=>11670, "width"=>400, "height"=>400, "filename"=>"image_processing20190805-29116-h0sc22.jpg", "mime_type"=>"image/jpeg"}}, "original"=>{"id"=>"0e27c1adf559c1cdb573a9e484da406a", "storage"=>"user_avatar_store", "metadata"=>{"size"=>21527, "width"=>1024, "height"=>1024, "filename"=>nil, "mime_type"=>"image/png"}}} isn't valid uploaded file data)
irb(main):011:0> 

I also tried having both the versions and derivatives plugins set up on the attacher at the same time, then calling User.last.avatar_derivatives!, but that didn't work either:

irb(main):004:0> User.last.avatar_derivatives!
Traceback (most recent call last):
        2: from (irb):4
        1: from app/uploaders/user_avatar_uploader.rb:28:in `block in <class:UserAvatarUploader>'
ImageProcessing::Error (invalid source: {:"50"=>#<UserAvatarUploader::UploadedFile storage=:user_avatar_store id="47f058aa5bb221865ecbc174e9ea8a43.jpg" metadata={"size"=>1506, "width"=>50, "height"=>50, "filename"=>"image_processing20190805-29116-70z2zj.jpg", "mime_type"=>"image/jpeg"}>, :"100"=>#<UserAvatarUploader::UploadedFile storage=:user_avatar_store id="a1ce120dd1ce311f8c7ccaefd6aeab02.jpg" metadata={"size"=>3032, "width"=>100, "height"=>100, "filename"=>"image_processing20190805-29116-1cwlcfc.jpg", "mime_type"=>"image/jpeg"}>, :"200"=>#<UserAvatarUploader::UploadedFile storage=:user_avatar_store id="f169756c5b77a5c2fb496a9cad9e48d7.jpg" metadata={"size"=>5965, "width"=>200, "height"=>200, "filename"=>"image_processing20190805-29116-hvmc56.jpg", "mime_type"=>"image/jpeg"}>, :"400"=>#<UserAvatarUploader::UploadedFile storage=:user_avatar_store id="4db360b3aec63452b382881c603a37e5.jpg" metadata={"size"=>11670, "width"=>400, "height"=>400, "filename"=>"image_processing20190805-29116-h0sc22.jpg", "mime_type"=>"image/jpeg"}>, :original=>#<UserAvatarUploader::UploadedFile storage=:user_avatar_store id="0e27c1adf559c1cdb573a9e484da406a" metadata={"size"=>21527, "width"=>1024, "height"=>1024, "filename"=>nil, "mime_type"=>"image/png"}>})

What is the correct way to migrate?

a...@abevoelker.com

unread,
Dec 16, 2019, 5:27:09 PM12/16/19
to Shrine
I just tried doing this with both the "versions" and "derivatives" plugin setup in the attacher at the same time:

User.each do |u|
[:"50", :"100", :"200", :"400"].each do |v|
x = u.avatar[v].download do |x|
u.avatar_attacher.add_derivative(v, x)
end
end
u.save!
end

But it had no effect.

If I run the above code on a single Rails model (u = User.last), u.avatar_derivatives does return a hash with data after the above code runs, but the u.save! is skipped because u.changed? returns false (i.e. u.avatar, the hash/JSONB data Shrine stores to has not changed). So as soon as I call u.reload, u.avatar_derivatives returns {} again.

Janko Marohnić

unread,
Dec 16, 2019, 6:33:25 PM12/16/19
to Shrine, a...@abevoelker.com
Hi Abe,

As shown in the upgrading guide, when switching from the versions plugin, you need to include the `versions_compatibility: true` flag when loading the derivatives plugin, so that it can read the "versions format" of the attachment column (and not throw the error you're seeing). Afterwards, you should migrate attachment data for all existing records to the "derivatives format", and then you should be able to remove the `versions_compatibility: true` flag.

Kind regards,
Janko
--
You received this message because you are subscribed to the Google Groups "Shrine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-shrine...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ruby-shrine/47f115d7-41a0-4fdc-b5b4-e5c123c24904%40googlegroups.com.

a...@abevoelker.com

unread,
Dec 17, 2019, 9:29:27 AM12/17/19
to Shrine
Well, that was easy! Thanks so much Janko. FWIW I did try googling it, and read the original GitHub issue, versions + derivatives plugin docs, and the 3.x release notes, but somehow missed there was an upgrade guide - very handy! I will consult that in the future.

Shrine continues to be amazing! 🥳 Thanks again for the excellent gem.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-...@googlegroups.com.

Janko Marohnić

unread,
Dec 17, 2019, 9:34:04 AM12/17/19
to Shrine, a...@abevoelker.com
Shrine continues to be amazing! 🥳 Thanks again for the excellent gem.

I'm very happy to heart that ❤️

Kind regards,
Janko
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-shrine...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ruby-shrine/7ff5d795-b514-45a5-85b2-85f2b57fb1c0%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages