Skip to content
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

Remove Paperclip and use just Active Storage #4600

Merged
merged 11 commits into from
Feb 24, 2022
Merged

Remove Paperclip and use just Active Storage #4600

merged 11 commits into from
Feb 24, 2022

Conversation

javierm
Copy link
Member

@javierm javierm commented Jul 28, 2021

References

Objectives

  • Fix a bug which caused document links to be broken if the document title was edited
  • Fix image preview not being rendered after submitting a form with validation errors
  • Fix wrong image preview when attaching an image, removing it, and attaching a different one
  • Improve file names when downloading documents
  • Make it possible to upgrade to Ruby 3 (Paperclip isn't compatible with Ruby 3)
  • Make it possible to switch from CKEditor to Action Text in the future

Release Notes

TODO Explain we've removed Paperclip but there might be references to paperclip attachments in any existing content (for example, custom pages) and so Paperclip attachments shouldn't be removed (or removed with care).

TODO Strongly emphasize that after upgrading it'll be necessary to execute the release tasks; othewise there'll be 500 errors on every page displaying an attached image or document.

@javierm javierm self-assigned this Jul 28, 2021
@javierm javierm added this to Reviewing in Consul Democracy via automation Jul 28, 2021
app/models/image.rb Outdated Show resolved Hide resolved
@javierm javierm force-pushed the active_storage branch 4 times, most recently from 1007e76 to fbcc669 Compare July 28, 2021 13:33
@javierm javierm force-pushed the active_storage branch 9 times, most recently from 479bebf to 09c08f8 Compare July 28, 2021 20:59
@javierm javierm force-pushed the active_storage branch 2 times, most recently from f4f7b75 to b1b0766 Compare July 28, 2021 21:28
@javierm javierm added the Bug label Jul 28, 2021
@javierm javierm force-pushed the active_storage branch 6 times, most recently from 445b713 to feebd88 Compare July 29, 2021 00:17
Base automatically changed from release_1.4.0 to master November 24, 2021 13:47
@javierm javierm changed the title [Do not merge] Remove Paperclip and use just Active Storage Remove Paperclip and use just Active Storage Dec 3, 2021
@javierm javierm marked this pull request as ready for review December 3, 2021 19:37
@javierm javierm requested a review from Senen December 29, 2021 21:26
Copy link
Member

@Senen Senen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good to me!

I did the following checks for testing these changes on a server running the production environment:

  1. Reproduce all the errors mentioned in the objectives section in the current master branch
  2. Deploy the branch active_storage
  3. Run the rake task to migrate attachments from paperclip to active_storage
  4. Check, one by one, all the errors mentioned in the objectives section are solved.
  5. Check the file_validators validations by uploading wrong sized and too heavy images and documents
  6. Check the ActiveStorage integration with AWS S3 works fine (including the Ckeditor specific integration)

Consul Democracy automation moved this from Reviewing to Testing Feb 23, 2022
@javierm
Copy link
Member Author

javierm commented Feb 23, 2022

For now, we'll merge it with the file_validators dependency 👌. We'll consider switching to active_storage_validations when they add support to procs in validations.

This way we fix a bug we mentioned in commit 930bb75 which caused
links to documents to be broken when editing their title because the
title was used to generate the URL of the document.

Note we're still using Paperclip to render cached attachments because
this is the only case where we store files with just Paperclip and not
Active Storage.

With Active Storage, we render attachments just like any other resource,
using `polymorphic_path`. Paperclip included the `url` method in the
model; since the model doesn't have access to the request parameters
(like the host), this was inconvenient because it wasn't possible to
generate absolute URLs with Paperclip.

In order to simplify the code and make it similar to the way we used
Paperclip, we're adding a `variant` method accepting the name of a
variant and returning the variant.
This fixes a few issues we've had for years.

First, when attaching an image and then sending a form with validation
errors, the image preview would not be rendered when the form was
displayed once again. Now it's rendered as expected.

Second, when attaching an image, removing it, and attaching a new
one, browsers were displaying the image preview of the first one. That's
because Paperclip generated the same URL from both files (as they both
had the same hash data and prefix). Browsers usually cache images and
render the cached image when getting the same URL.

Since now we're storing each image in a different Blob, the images have
different URLs and so the preview of the second one is correctly
displayed.

Finally, when users downloaded a document, they were getting files with
a very long hexadecimal hash as filename. Now they get the original
filename.
Just like we did with regular attachments, we're moving the logic to
generate URLs out of the model.

Note we're changing the `image_path_for` helper method in order to
return a `polymorphic_path` because sometimes it's used in combination
with `favicon_link_tag`, and `favicon_link_tag` doesn't automatically
generate a polymorphic URL when given an `ActiveStorage::Attachment`
record.
The same way we're handling images.
Since we're going to remove Paperclip and Active Storage doesn't provide
any validations, we have to either write our own validation rules or use
a different gem.

We're using the file_validators gem instead of the
`active_storage_validations` gem because the latter doesn't support
proc/lambda objects in size and content type definitions. We need to use
them because in our case these values depend on settings stored in the
database.
The code is based on what's generated using CKEditor's code generator.

We're doing one minor change to the `Ckeditor::Backend::ActiveStorage`
module; we're assigning the data in a `before_validation` instead of a
`before_save` callback. Validations with `file_validations` didn't work
otherwise; it looks like this backend was written with
`active_storage_validations` in mind [1].

Note we don't need to update the `name` column in the attachments table
because, when using Active Storage, CKEditor uses both `data` (as
attribute accessor) and `storage_data` (as attachment attribute).

[1] https://github.com/galetahub/ckeditor/blob/f9e48420ccb6dc/lib/generators/ckeditor/templates/active_record/active_storage/ckeditor/picture.rb#L4
We were getting an error when browsing the server if one file had been
deleted.
@javierm javierm force-pushed the active_storage branch 3 times, most recently from af1ff53 to 303442c Compare February 23, 2022 17:43
We were using custom rules because of some issues with Paperclip. These
rules work fine, but since we're already using the file_validators gem,
we might as well simplify the code a little bit.
This way we don't have to write `"spec/fixtures/files"` every time.

Note this method isn't included in factories. We could include it like
so:

```
FactoryBot::SyntaxRunner.class_eval do
  include ActiveSupport::Testing::FileFixtures
  self.file_fixture_path = RSpec.configuration.file_fixture_path
end
```

However, I'm not sure about the possible side effects, and since we only
use attachments in a few factories, there isn't much gain in applying
the monkey-patch.
We were using this hack in order to allow `File.new` attachments in
tests files. However, we can use the `fixture_file_upload` helper
instead.

Just like it happened with `file_fixture`, this helper method doesn't
work in fixtures, so in this case we're using `Rack::Test::UploadedFile`
instead.
@javierm javierm merged commit 193b61a into master Feb 24, 2022
Consul Democracy automation moved this from Testing to Release 1.5.0 Feb 24, 2022
@javierm javierm deleted the active_storage branch February 24, 2022 15:32
@taitus taitus mentioned this pull request Jun 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Integrate Ckeditor with Amazon S3 uploads Move to ActiveStorage
2 participants