Rails 6.0 升级后,ActiveStorage 不会将 blob 持久保存到附件
ActiveStorage not persisting blob to attachment after Rails 6.0 upgrade
我的 ActiveStorage 有一个问题,似乎是因为 Rails 6.0 升级(从 5.2.x)。
我有一个自定义管理界面,其中页面有字段,每个字段都有一个 STI type
来创建复杂的页面布局。使用 Active Storage 的 Image
类型(它是 Paperclip,但在 Rails 5.2 发布后迁移)通过简单的上传模式存储图像 - 没有复杂的直接上传 JS。
class 结构如下所示(为简洁起见,我删除了额外的代码):
class Page < ApplicationRecord
has_many :fields, dependent: :destroy
accepts_nested_attributes_for :fields, allow_destroy: true
end
class Field < ApplicationRecord
belongs_to :page
end
module Fields
class Image < Content::Field
has_one_attached :image
accepts_nested_attributes_for :image_attachment, allow_destroy: true
end
end
当页面更新时,它是通过嵌套的表单属性和对 @page.update(permitted_params)
的简单调用来实现的。
permitted_params
(减去不重要的参数),看起来像这样...
{
"fields_attributes"=> {
"0"=> {
"type"=>"Fields::Image",
"image"=>#<ActionDispatch::Http::UploadedFile:0x00007ff36cdd9908 @tempfile=#<Tempfile:/var/folders/_t/clkdb5ms365617_039m7y7sc0000gn/T/RackMultipart20191021-38488-4kyp8k.jpg>, @original_filename="image.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"content_page[fields_attributes][0][image]\"; filename=\"image.jpg\"\r\nContent-Type: image/jpeg\r\n">,
"id"=>"8059"
}
}
}
为了保持更新集合而不是覆盖它的 ActiveStorage 5.2 行为,我的 application.rb
中有以下内容:
config.active_storage.replace_on_assign_to_many = false
但是,因为字段关系是has_one_attached
,这应该不会影响它。
根据日志,没有开始上传,也没有对 Active Storage table 进行任何更新,但有一个更新写入 Page
table:
Content::Page Update (5.2ms) UPDATE `pages` SET `pages`.`updated_at` = '2019-10-21 13:58:18' WHERE `pages`.`id` = 105 /*application:myapp,controller:pages,action:update*/
仅此而已,没有别的。
但是,如果我byebug
在更新方法中然后手动执行更新:
$ img = Fields::Image.new(image: permitted_params.dig("fields_attributes", "0", "image"))
#<Content::Fields::Image id: nil, type: "Content::Fields::Image">
$ img.valid?
# true
$ img.save
(4.6ms) BEGIN
Field Load (1.5ms) SELECT `fields`.* FROM `fields` WHERE `fields`.`page_id` IS NULL AND (`fields`.`position` IS NOT NULL) ORDER BY `fields`.`position` DESC LIMIT 1
Fields::Image Create (1.7ms) INSERT INTO `fields` (`type`) VALUES ('Fields::Image')
ActiveStorage::Blob Load (1.6ms) SELECT `active_storage_blobs`.* FROM `active_storage_blobs` INNER JOIN `active_storage_attachments` ON `active_storage_blobs`.`id` = `active_storage_attachments`.`blob_id` WHERE `active_storage_attachments`.`record_id` = 8062 AND `active_storage_attachments`.`record_type` = 'Fields::Image' AND `active_storage_attachments`.`name` = 'image' ORDER BY `active_storage_attachments`.`position` ASC LIMIT 1
ActiveStorage::Attachment Load (1.6ms) SELECT `active_storage_attachments`.* FROM `active_storage_attachments` WHERE `active_storage_attachments`.`record_id` = 8062 AND `active_storage_attachments`.`record_type` = 'Fields::Image' AND `active_storage_attachments`.`name` = 'image' ORDER BY `active_storage_attachments`.`position` ASC LIMIT 1
ActiveStorage::Blob Create (2.7ms) INSERT INTO `active_storage_blobs` (`key`, `filename`) VALUES ('mnf9brbh9e1kyriummf11kpd7t6q', 'image.jpg')
ActiveStorage::Attachment Load (2.0ms) SELECT `active_storage_attachments`.* FROM `active_storage_attachments` WHERE `active_storage_attachments`.`record_type` = 'Fields::Image' AND `active_storage_attachments`.`name` = 'image' AND `active_storage_attachments`.`record_id` = 8062 AND (`active_storage_attachments`.`position` IS NOT NULL) ORDER BY `active_storage_attachments`.`position` DESC LIMIT 1
ActiveStorage::Attachment Create (4.1ms) INSERT INTO `active_storage_attachments` (`name`, `record_type`, `record_id`) VALUES ('image', 'Fields::Image')
Fields::Image Update (2.3ms) UPDATE `fields` SET `fields`.`updated_at` = '2019-10-21 14:24:06' WHERE `fields`.`id` = 8062
(2.0ms) COMMIT
FlatDisk Storage (5.3ms) Uploaded file to key: mnf9brbh9e1kyriummf11kpd7t6q (checksum: ms9Zu1oagR5kGjcci1YfhQ==)
[ActiveJob] Enqueued ActiveStorage::AnalyzeJob (Job ID: 034d495a-01c1-4935-a873-b07fcec35f47) to Sidekiq(active_storage_analysis) with arguments: #<GlobalID:0x00007ff36c2e2090 @uri=#<URI::GID gid://dswt/ActiveStorage::Blob/52786>>
# true
所以这让我认为这可能与嵌套参数有关,但我看不出这些有什么问题,所以我对可能发生的事情感到困惑。
图像上传在网站的其他地方正常运行,只是在这个地方它们没有按预期工作。
如有任何帮助,我们将不胜感激。
谢谢你,保罗。
编辑:
我已将其缩小到 ActiveStorage 不更新图像关联,除非模型上的字段(updated_at
或 table 上的任何列)也被更新。这似乎会触发 ActiveRecord 持久化实例,从而触发 ActiveStorage 上传文件。
经过一番尝试后,我发现除非以某种方式更改模型,否则不会更新活动存储关系,例如,触摸 updated_at
时间戳,或另一个编辑另一个字段 -我认为这是一个 Rails 错误。
通过在我的表单中添加 <%= f.hidden_field :updated_at, value: DateTime.current %>
,我能够强制 Active Storage 保留文件。
希望这对其他人有帮助。
我的 ActiveStorage 有一个问题,似乎是因为 Rails 6.0 升级(从 5.2.x)。
我有一个自定义管理界面,其中页面有字段,每个字段都有一个 STI type
来创建复杂的页面布局。使用 Active Storage 的 Image
类型(它是 Paperclip,但在 Rails 5.2 发布后迁移)通过简单的上传模式存储图像 - 没有复杂的直接上传 JS。
class 结构如下所示(为简洁起见,我删除了额外的代码):
class Page < ApplicationRecord
has_many :fields, dependent: :destroy
accepts_nested_attributes_for :fields, allow_destroy: true
end
class Field < ApplicationRecord
belongs_to :page
end
module Fields
class Image < Content::Field
has_one_attached :image
accepts_nested_attributes_for :image_attachment, allow_destroy: true
end
end
当页面更新时,它是通过嵌套的表单属性和对 @page.update(permitted_params)
的简单调用来实现的。
permitted_params
(减去不重要的参数),看起来像这样...
{
"fields_attributes"=> {
"0"=> {
"type"=>"Fields::Image",
"image"=>#<ActionDispatch::Http::UploadedFile:0x00007ff36cdd9908 @tempfile=#<Tempfile:/var/folders/_t/clkdb5ms365617_039m7y7sc0000gn/T/RackMultipart20191021-38488-4kyp8k.jpg>, @original_filename="image.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"content_page[fields_attributes][0][image]\"; filename=\"image.jpg\"\r\nContent-Type: image/jpeg\r\n">,
"id"=>"8059"
}
}
}
为了保持更新集合而不是覆盖它的 ActiveStorage 5.2 行为,我的 application.rb
中有以下内容:
config.active_storage.replace_on_assign_to_many = false
但是,因为字段关系是has_one_attached
,这应该不会影响它。
根据日志,没有开始上传,也没有对 Active Storage table 进行任何更新,但有一个更新写入 Page
table:
Content::Page Update (5.2ms) UPDATE `pages` SET `pages`.`updated_at` = '2019-10-21 13:58:18' WHERE `pages`.`id` = 105 /*application:myapp,controller:pages,action:update*/
仅此而已,没有别的。
但是,如果我byebug
在更新方法中然后手动执行更新:
$ img = Fields::Image.new(image: permitted_params.dig("fields_attributes", "0", "image"))
#<Content::Fields::Image id: nil, type: "Content::Fields::Image">
$ img.valid?
# true
$ img.save
(4.6ms) BEGIN
Field Load (1.5ms) SELECT `fields`.* FROM `fields` WHERE `fields`.`page_id` IS NULL AND (`fields`.`position` IS NOT NULL) ORDER BY `fields`.`position` DESC LIMIT 1
Fields::Image Create (1.7ms) INSERT INTO `fields` (`type`) VALUES ('Fields::Image')
ActiveStorage::Blob Load (1.6ms) SELECT `active_storage_blobs`.* FROM `active_storage_blobs` INNER JOIN `active_storage_attachments` ON `active_storage_blobs`.`id` = `active_storage_attachments`.`blob_id` WHERE `active_storage_attachments`.`record_id` = 8062 AND `active_storage_attachments`.`record_type` = 'Fields::Image' AND `active_storage_attachments`.`name` = 'image' ORDER BY `active_storage_attachments`.`position` ASC LIMIT 1
ActiveStorage::Attachment Load (1.6ms) SELECT `active_storage_attachments`.* FROM `active_storage_attachments` WHERE `active_storage_attachments`.`record_id` = 8062 AND `active_storage_attachments`.`record_type` = 'Fields::Image' AND `active_storage_attachments`.`name` = 'image' ORDER BY `active_storage_attachments`.`position` ASC LIMIT 1
ActiveStorage::Blob Create (2.7ms) INSERT INTO `active_storage_blobs` (`key`, `filename`) VALUES ('mnf9brbh9e1kyriummf11kpd7t6q', 'image.jpg')
ActiveStorage::Attachment Load (2.0ms) SELECT `active_storage_attachments`.* FROM `active_storage_attachments` WHERE `active_storage_attachments`.`record_type` = 'Fields::Image' AND `active_storage_attachments`.`name` = 'image' AND `active_storage_attachments`.`record_id` = 8062 AND (`active_storage_attachments`.`position` IS NOT NULL) ORDER BY `active_storage_attachments`.`position` DESC LIMIT 1
ActiveStorage::Attachment Create (4.1ms) INSERT INTO `active_storage_attachments` (`name`, `record_type`, `record_id`) VALUES ('image', 'Fields::Image')
Fields::Image Update (2.3ms) UPDATE `fields` SET `fields`.`updated_at` = '2019-10-21 14:24:06' WHERE `fields`.`id` = 8062
(2.0ms) COMMIT
FlatDisk Storage (5.3ms) Uploaded file to key: mnf9brbh9e1kyriummf11kpd7t6q (checksum: ms9Zu1oagR5kGjcci1YfhQ==)
[ActiveJob] Enqueued ActiveStorage::AnalyzeJob (Job ID: 034d495a-01c1-4935-a873-b07fcec35f47) to Sidekiq(active_storage_analysis) with arguments: #<GlobalID:0x00007ff36c2e2090 @uri=#<URI::GID gid://dswt/ActiveStorage::Blob/52786>>
# true
所以这让我认为这可能与嵌套参数有关,但我看不出这些有什么问题,所以我对可能发生的事情感到困惑。
图像上传在网站的其他地方正常运行,只是在这个地方它们没有按预期工作。
如有任何帮助,我们将不胜感激。
谢谢你,保罗。
编辑:
我已将其缩小到 ActiveStorage 不更新图像关联,除非模型上的字段(updated_at
或 table 上的任何列)也被更新。这似乎会触发 ActiveRecord 持久化实例,从而触发 ActiveStorage 上传文件。
经过一番尝试后,我发现除非以某种方式更改模型,否则不会更新活动存储关系,例如,触摸 updated_at
时间戳,或另一个编辑另一个字段 -我认为这是一个 Rails 错误。
通过在我的表单中添加 <%= f.hidden_field :updated_at, value: DateTime.current %>
,我能够强制 Active Storage 保留文件。
希望这对其他人有帮助。