Reputation: 46
I have a problem for ActiveStorage
the case is I have a model named Setting::Profile
and name of Admin
table and attachment :avatar
for uploading process succeed, but when to get the picture can not be found because at table active_storage_attachments
in attribute record_type
stored with name Setting::Profile
, supposed with name Admin
How to add a line to prepare for the record_type
attribute?
Thanks
This my demo: https://github.com/SunDi3yansyah-forks/AppActiveStorage
Upvotes: 3
Views: 1851
Reputation: 11193
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
.
Upvotes: 4