r3b00t
r3b00t

Reputation: 7533

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

I am using Active Storage to store images for match score. My class looks like this

class TournamentMatch < ApplicationRecords
  has_many_attached :score_cards
end

My Score card controller looks like this

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

So in my create action,I am finding TournamentMatch by id and then attaching score card to it. I am using same image file each time for uploading. But sometimes image is getting attached and sometime it doesn't. tournament_match.score_cards.attach(params['score_cards'] always returns true in controller. But if i find the same tournament_match and run tournament_match.score_cards.attach(params['score_cards'] in console then it's returning false. I have also noticed that record_id for active_storage_attachments is set to 0 when ever image is not saved. But if image is saved then record_id have value greater than 0.

I have run out of ideas for debugging. Please suggest me how to debug this problem.

Update: below query is from log file, it shows record_id is nil

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

Upvotes: 2

Views: 2029

Answers (2)

stevec
stevec

Reputation: 52198

For new rails 7 apps, inside the ActiveStorage migration file, change this

primary_key_type, foreign_key_type = primary_and_foreign_key_types

to this

primary_key_type, foreign_key_type = [:uuid, :uuid]

It will work now.

Notes

  • I think this means if you want attachments on any model that has uuid as its primary key, then you'll need to make sure all models which you intend to have attachments also use uuid i.e. you can't mix and match (at least, I don't know how).
  • See here for how to set uuid as the default primary key for all generators across the application.

References

The ActiveStorage docs says:

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.

More reading here for older rails versions.

Upvotes: 1

r3b00t
r3b00t

Reputation: 7533

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

Upvotes: 5

Related Questions