我使用的是Rails 6.1和Active Storage,并且有一个附带海报的模型电影。
一切都很好,但在我删除了一张旧海报后,我似乎无法附上一张新海报——我得到了
FrozenError (can't modify frozen attributes)
以下是有问题的方法的电影模型:
class Movie < ApplicationRecord
...
has_one_attached :poster
...
# technically this method is defined in application_record.rb as it is needed elsewhere too
def grab_picture(input, output)
unless input.nil? || input.empty?
picture_attach = URI.open(input)
picture_name = File.basename(picture_attach.path)
if output.attached?
output.purge
end
output.attach(io: picture_attach, filename: picture_name)
end
end
在rails控制台上,我可以做这样的事情(假设m是一个附有海报的电影对象(:
> m.poster.attached?
=> true
> m.poster.purge
...
> m.poster.attached?
=> false
> m.grab_picture('some_image_url', m.poster)
=> #<ActiveStorage::Attached::Changes::CreateOne:0x00007fd4bd90d488 @attachable={:io=>#<Tempfile:/var/folders/m3/6_527vrn01b1rz0lns767dv80000gn/T/open-uri20220120-2419-8vq9td>, :filename=>"open-uri20220120-2419-8vq9td"}, @record=#<Movie id: 89, title: "The Avengers", runtime: 143, release_year: 2012, sort_title: "Avengers", created_at: "2022-01-19 13:31:00.176136000 +0000", updated_at: "2022-01-20 08:07:34.590191000 +0000", country: "US">, @name="poster", @blob=#<ActiveStorage::Blob id: nil, key: nil, filename: "open-uri20220120-2419-8vq9td", content_type: "image/jpeg", metadata: {"identified"=>true}, service_name: "local", byte_size: 1093283, checksum: "iQ+KdZxaPI1TavdrT4mpDw==", created_at: nil>>
irb(main):016:0> m.grab_picture(m.image_url, m.poster)
TRANSACTION (1.6ms) BEGIN
Movie Update (1.8ms) UPDATE `movies` SET `movies`.`updated_at` = '2022-01-20 08:08:40.457643' WHERE `movies`.`id` = 89
TRANSACTION (8.1ms) COMMIT
Disk Storage (9.5ms) Uploaded file to key: kryn45dplbsd5i8ag9rjrhd7xk8w (checksum: iQ+KdZxaPI1TavdrT4mpDw==)
TRANSACTION (2.0ms) BEGIN
ActiveStorage::Attachment Exists? (1.5ms) SELECT 1 AS one FROM `active_storage_attachments` WHERE `active_storage_attachments`.`blob_id` IS NULL AND (1=0) LIMIT 1
TRANSACTION (1.7ms) COMMIT
Disk Storage (0.4ms) Deleted file from key: kryn45dplbsd5i8ag9rjrhd7xk8w
Disk Storage (0.2ms) Deleted files by key prefix: variants/kryn45dplbsd5i8ag9rjrhd7xk8w/
TRANSACTION (1.3ms) BEGIN
Movie Exists? (2.0ms) SELECT 1 AS one FROM `movies` WHERE `movies`.`title` = 'The Avengers' AND `movies`.`id` != 89 LIMIT 1
Movie Update (1.8ms) UPDATE `movies` SET `movies`.`updated_at` = '2022-01-20 08:08:40.661803' WHERE `movies`.`id` = 89
ActiveStorage::Attachment Exists? (1.9ms) SELECT 1 AS one FROM `active_storage_attachments` WHERE `active_storage_attachments`.`blob_id` IS NULL AND (1=0) LIMIT 1
TRANSACTION (1.8ms) ROLLBACK
Traceback (most recent call last):
4: from (irb):16:in `<main>'
3: from app/models/application_record.rb:18:in `grab_picture'
2: from app/models/movie.rb:72:in `block in <class:Movie>'
1: from app/models/application_record.rb:16:in `grab_picture'
FrozenError (can't modify frozen attributes)
我不完全理解这一点。哪些属性被冻结?我需要做什么额外的步骤才能完全移除海报附件?请注意,把一张照片附加到一部从未有过照片的电影上没有问题吗?
编辑:经过一些测试:我实际上可以在已经有海报的现有电影上贴上一张新海报;重写";可以说是依恋。但我试图实现的功能是可以移除海报(并可能在之后的某个时候附加另一张海报(。这就是我正在挣扎的地方。
ActiveStorage::Blob#purge
破坏blob记录,冻结其属性。
尝试在不清除前一张图片的情况下附加新图片。ActiveStorage将在内部为您做到这一点。