New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ActiveStorage] Fix TransformJob to preprocess preview image variant #50026
Conversation
Followup rails#50006 Every `ActiveStorage::Blob` has a `has_one_attached :preview_image` which is technically another AS blob. Right now `ActiveStorage::Preview#processed` only generates the `preview_image` blob, but not the variant that's associated with it (with transformations available in the `@variations` instance variable) One way to solve this is to force the `ActiveStorage::TransformJob` to preprocess the variant as well by calling `ActiveStorage::Preview#key` this would return the key value that's inside the variant, which can be safely discarded in the context of `ActiveStorage::TransformJob` The `ActiveStorage::Preview#processed` method can be subject to a refactor to handle multiple transformations depending on the `@variation` instance variable.
db2a169
to
9dd2de7
Compare
@blob = create_file_blob(filename: "report.pdf", content_type: "application/pdf") | ||
transformations = { resize_to_limit: [100, 100] } | ||
|
||
assert_changes -> { @blob.reload.preview_image.variant(transformations)&.send(:processed?) }, from: nil, to: true do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the preview_image does not exist before calling the job, variant(transformations) returns nil, that's why i had to add th &.send
@@ -7,6 +7,6 @@ class ActiveStorage::TransformJob < ActiveStorage::BaseJob | |||
retry_on ActiveStorage::IntegrityError, attempts: 10, wait: :polynomially_longer | |||
|
|||
def perform(blob, transformations) | |||
blob.representation(transformations).processed | |||
blob.representation(transformations).processed.key |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since representation
makes the assumption that it returns an object that responds to processed
, I figured it wouldn't hurt to add this key
call
@jonathanhefner
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(also key and url are publicly documented methods are usually used after calling processed
cf. guide )
I can confirm that this works for me. The variant of the preview is now being pre-generated as it should. However I still don't get why simply calling |
@nicowenterodt A bit magical but if you look at either rails/activestorage/app/models/active_storage/preview.rb Lines 72 to 78 in 9194b33
and rails/activestorage/app/models/active_storage/preview.rb Lines 106 to 108 in 9194b33
which itself creates the variant AND calls Since It took me a bit of time to be 100% sure of what's happening. Maybe variant should become a public instance method instead. EDIT : Oh and rails/activestorage/app/models/active_storage/preview.rb Lines 54 to 56 in 9194b33
and |
d08d652
to
0d68e59
Compare
TransformJob
to preprocess preview image variant0d68e59
to
9dd2de7
Compare
@chaadow thanks for pinpointing this one out. 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for investigating this! I think the best approach is similar to your most recent commit — changing ActiveStorage::Preview#processed
to also process the variant. However, as you probably noticed, that causes some tests to fail.
I have been working on a similar solution. I addressed the test failures in #50043 (and #50041), and I've just submitted #50044 with you as a co-author.
@jonathanhefner thank you. while spelunking the code and tests, I realized the tests in Is it possible to push your code onto my PR, or should I create a new PR. test "previewing a PDF" do
blob = create_file_blob(filename: "report.pdf", content_type: "application/pdf")
# variation = { resize_to_limit: [640, 280] }
preview = blob.preview({}).processed
assert_predicate preview.image, :attached?
assert_equal "report.png", preview.image.filename.to_s
assert_equal "image/png", preview.image.content_type
image = read_image(preview.image)
assert_equal 612, image.width
assert_equal 792, image.height
end 1 - At first i thought that 2- also i was wondering if we pass an empty hash, should we add a conditional to skip the 3- Just like this test, I would like to add a new test that |
If I understand correctly, I think the way the test is currently written is better. It tests that the preview image has an expected size even when a variant is specified. In other words, that specifying a variant does not impact the full-sized preview image. But if I am misunderstanding, feel free to open a PR so I can see the proposed change.
Maybe...? I would have to dig into it to see whether it would be feasible / good. But feel free to open a PR for that as well, if you think it would be an improvement. |
Followup #50006 cc @jonathanhefner @nicowenterodt
Motivation / Background
This Pull Request has been created because
TransformJob
for previewable files only preprocess the preview image, but not the associated preview_image variant.Detail
This Pull Request changes
ActiveStorage::TransformJob
to also trigger the preprocessing of the variant. It is also compatible with both previewable and variable records, as they both implement the#key
methodAdditional information
Every
ActiveStorage::Blob
has ahas_one_attached :preview_image
which is technically another AS blob.Right now
ActiveStorage::Preview#processed
only generates thepreview_image
blob, but not the variant that's associated with it (with transformations available in the@variation
instance variable)One way to solve this is to force the
ActiveStorage::TransformJob
to preprocess the variant as well by callingActiveStorage::Preview#key
( orActiveStorage::Variant#key
but it just calculates a key here) this would return the key value that's inside the variant, which can be safely discarded in the context ofActiveStorage::TransformJob
The
ActiveStorage::Preview#processed
method can be subject to a refactor to handle multiple transformations depending on the@variation
instance variable ( which might require refactoring the#processed?
method )the
ActiveStorage::Preview#key
, as well asActiveStorage::Preview#url
, also can be refactored, because right now they perform two things:Compared to the
ActiveStorage::Variant#key
that simply calculates a keyChecklist
Before submitting the PR make sure the following are checked:
[Fix #issue-number]