why active storage record id is null and upload too slow

Viewed 568

I am using latest rails and ruby for a new project, I am using Active Storage for upload files ( images and videos ) to GCP, when I upload multiples files about 13-18 images, it takes too long to upload and when I check on my database after it finished, my record_id is 0 ? is there something wrong?

class Gallery < ApplicationRecord
  has_many_attached :files
end

my gallery id is UUID for the primary key is this caused by this? because on their documentations said

If you are using UUIDs instead of integers as the primary key on your models 
you will need to change the column type of "record_id"
for the active_storage_attachments table in the generated migration accordingly.
2 Answers

I ran into this as well:

It is because the record_id column is of type integer. When you try to enter a uuid into it the following happens and you get the record_id 0 for most attachments:

2.7.0 :001 > "a2".to_i
 => 0
2.7.0 :002 > "2a".to_i
 => 2

In the migration that is created when you set up ActiveStorage there is a line that looks like this:

t.references :record, null: false, polymorphic: true, index: false

For use with UUIDs you'll have to add type: :uuid in order to set the type of the foreign key explicitly.

When the model you're attaching to uses uuid as it's primary key, you have to let ActiveStorage know about it.

Two symptoms (that I know of) of not doing so, are

  • ActiveStorage uploads will be intermittent (due to null id)
  • An error like this
NoMethodError (undefined method 'attachment_reflections' for nil:NilClass):

Solution

In a new rails 7 app, simply go into the ActiveStorage migration file and change this line:

primary_key_type, foreign_key_type = primary_and_foreign_key_types

to this:

primary_key_type, foreign_key_type = [:uuid, :uuid]

Then ActiveStorage will work as expected.

More info here. Note that you may even wish to set the default primary key type to uuid across your application.


Another (unrelated) reason for slow uploads

Another thing that could cause slow uploads is if you try to pass the ActiveStorage attachements through .update! like this

article.update!(
  content: article_params[:content],
  photos: article_params[:photos],
  videos: article_params[:videos]
  )

do this instead:

article.update!(content: article_params[:content])
article.photos.attach(article_params[:photos]) 
article.videos.attach(article_params[:videos]) 

I made this mistake and it took 17 seconds on heroku for 2 uploads totalling 6mb; after the change it took 6 seconds!

Related