Rails Active Storage 并非每次都有效。有时有效,有时无效

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

我正在使用 Active Storage 来存储匹配分数的图像。我的 class 看起来像这样

class TournamentMatch < ApplicationRecords
  has_many_attached :score_cards
end

我的记分卡控制器是这样的

class Public::ScoreCardsController < Public::BaseController
  def new
    session[:tournament_match_id] = params[:tournament_match_id]
  end

  def create
    tournament_match_id = session[:tournament_match_id]
    tournament_id = session[:tournament_id]
    session[:tournament_match_id] = nil
    session[:tournament_id] = nil

    tournament_match = TournamentMatch.find_by(id: tournament_match_id)

    if tournament_match.score_cards.attach(params['score_cards'])
      flash[:notice] = 'Score card uploaded'
    else
      flash[:error] = 'Score card upload failed'
    end
      
    redirect_to public_results_path(tournament_id: "#{tournament_id}/", anchor: 'results')
  end

  def view
    @tournament_match = TournamentMatch.find_by(id: params[:tournament_match_id])
    render layout: "application"
  end
end

所以在我的创建操作中,我通过 ID 找到 TournamentMatch,然后将记分卡附加到它。我每次都使用相同的图像文件进行上传。但有时图像会被附加,有时则不会。 tournament_match.score_cards.attach(params['score_cards'] 在控制器中始终 returns 为真。但是,如果我在控制台中找到相同的 tournament_match 和 运行 tournament_match.score_cards.attach(params['score_cards'],那么它会返回 false。我还注意到 record_id for active_storage_attachments 在未保存图像时设置为 0。但是,如果图像被保存,则 record_id 的值大于 0。

我 运行 没有调试的想法。请建议我如何调试此问题。

更新:以下查询来自日志文件,显示 record_id 为 nil

ActiveStorage::Attachment Exists? (0.6ms)  SELECT 1 AS one FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" =  AND "active_storage_attachments"."record_type" =  AND "active_storage_attachments"."name" =  LIMIT   [["record_id", nil], ["record_type", "TournamentMatch"], ["name", "score_cards"], ["LIMIT", 1]]

我的主要问题是我使用 :uuid 作为我所有表的主键,所以我必须编辑 ActiveStorage 迁移以使用 :uuid。我主要更改了这两行 t.references :record, null: false, polymorphic: true, index: false, type: :uuidt.references :blob, null: false, type: :uuid。我的最终迁移看起来像这样。之后 ActiveStorage 就可以正常工作了。

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

对于新的 rails 7 个应用程序,在 ActiveStorage 迁移文件中,更改此

primary_key_type, foreign_key_type = primary_and_foreign_key_types

至此

primary_key_type, foreign_key_type = [:uuid, :uuid]

现在可以使用了。

备注

  • 我认为这意味着如果你想在任何以 uuid 作为主键的模型上添加附件,那么你需要确保 all 个你打算有附件的模型也使用 uuid 即你不能混合搭配(至少,我不知道如何)。
  • 请参阅 了解如何将 uuid 设置为应用程序中所有生成器的默认主键。

参考资料

ActiveStorage docs 说:

If you are using UUIDs instead of integers as the primary key on your models you will need to change the column type of active_storage_attachments.record_id and active_storage_variant_records.id in the generated migration accordingly.

更多阅读 here 旧 rails 版本。