Activestorage Issue to Set Record_Type on Active_Storage_Attachments

ActiveStorage issue to set record_type on active_storage_attachments

I found this problem (try in console).

If you set profile = Account::Profile.last then call profile.avatar.attached? it returns false. This is because the column record_type in ActiveStorage::Attachment is set to User.

So, you can not access the blob because profile.avatar.blob returns the following query:

SELECT  "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 1], ["record_type", "Account::Profile"], ["name", "avatar"], ["LIMIT", 1]]

And the error: Module::DelegationError: blob delegated to attachment, but attachment is nil

One possible workaround that I found is to define Account::Profile as follows:

class Account::Profile < ApplicationRecord
self.table_name = "users"
# has_one_attached :avatar # remove this

def avatar
ActiveStorage::Attachment.where(name: :avatar, record_type: 'User', record_id: self.id).last
end

end

This works for showing the image but has the problem that profile.avatar.class is not ActiveStorage::Attached::One (like User.last.avatar.class) but ActiveStorage::Attachment.

So, you can not call for example .attached? method on it. You must use profile.avatar.present? to check if the avatar is present.

A possible better solution is to define the instance method avatar in this way:

def avatar
ActiveStorage::Attached::One.new('avatar', User.find(id), dependent: :purge_later)
end

It is required to instantiate an object of ActiveStorage::Attached::One but the record must be User class (to match record_type), that's why User.find(id).
Now all methods are available: profile.avatar.methods.

Rails Active Storage not working every time. Some time it works, sometime it doesn't

My main problem was that I am using :uuid for primary key for all my tables so I has to edit ActiveStorage migration to use :uuid. I had changed mainly these 2 lines t.references :record, null: false, polymorphic: true, index: false, type: :uuid and t.references :blob, null: false, type: :uuid. My final migration looks like this. And after this ActiveStorage is now woking fine.

class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
def change
create_table :active_storage_blobs, id: :uuid do |t|
t.string :key, null: false
t.string :filename, null: false
t.string :content_type
t.text :metadata
t.bigint :byte_size, null: false
t.string :checksum, null: false
t.datetime :created_at, null: false

t.index [ :key ], unique: true
end

create_table :active_storage_attachments, id: :uuid do |t|
t.string :name, null: false
t.references :record, null: false, polymorphic: true, index: false, type: :uuid
t.references :blob, null: false, type: :uuid

t.datetime :created_at, null: false

t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
end
end

ActiveStorage not persisting blob to attachment after Rails 6.0 upgrade

After a bunch of playing around I worked out that the Active Storage relationships were not being updated unless the model was altered in some way, for example, touching the updated_at timestamp, or another editing another field - I think this is a Rails bug.

By Adding <%= f.hidden_field :updated_at, value: DateTime.current %> in my forms, I was able to force Active Storage to persist the file.

Hope this helps someone else.

Rails ActiveStorage scope for when file is NOT attached

You can do that using left_joins with the name of the association (image + _attachment) which is interpreted as:

SELECT users.*
FROM users LEFT OUTER JOIN active_storage_attachments
ON active_storage_attachments.record_id = users.id
AND active_storage_attachments.record_type = 'User'
AND active_storage_attachments.name = 'image'

And then apply a WHERE filter to get those user rows without match against the active_storage_attachments table:

User.left_joins(:image_attachment).where(active_storage_attachments: { id: nil })

Active Storage Rails 6 API unable to insert to active_storage_attachments table

I add a new method for attachment this is my refactor code. Hope this will help.

class Api::V1::UploadController < ActiveStorage::DirectUploadsController

skip_before_action :verify_authenticity_token

def create
blob = ActiveStorage::Blob.create_before_direct_upload!(blob_args)
render json: direct_upload_json(blob)
end

def attached_create
ActiveStorage::Attachment.create(params_attached) #from react axios pass params
end

private

def params_attached
params.require(:attachment).permit(:name, :record_type, :record_id, :blob_id)
end

def blob_args
params.require(:blob).permit(:filename, :byte_size, :checksum, :content_type, metadata: {}).to_h.symbolize_keys
end

def direct_upload_json(blob)
blob.as_json(root: false, methods: :signed_id).merge(service_url: url_for(blob)).merge(direct_upload: {
url: blob.service_url_for_direct_upload,
headers: blob.service_headers_for_direct_upload
})
end

Rails: Reducing the amount of ActiveStorage queries

Depending in your case (has_many/has_one) use with_attached_<attachment>:

To avoid N+1 queries, you can include the attached blobs in your query
like so:

Gallery.where(user: Current.user).with_attached_photos

So:

[
Album.all,
Demo.with_attached_images.all,
Samplepack.with_attached_images.all
]

I think there's no need to create an empty array to fill it then.

There's perhaps also a problem since you're using all, check what you really need from each model.



Related Topics



Leave a reply



Submit