maglev-core: Unable to upload or display uploaded images when using UUIDs and Postgres

I’ve setup active_storage but uploads keep failing…

Started POST "/maglev/api/assets" for ::1 at 2023-12-07 21:35:31 -0500
Processing by Maglev::Api::AssetsController#create as JSON
  Parameters: {"asset"=>{"file"=>#<ActionDispatch::Http::UploadedFile:0x000000010b8925e0 @tempfile=#<Tempfile:/var/folders/fd/04qkytls0xxc3nhjyccdw3vm0000gn/T/RackMultipart20231207-22731-6ci014.jpg>, @content_type="image/jpeg", @original_filename="fabian-centeno-uY60pJUHqOo-unsplash.jpg", @headers="Content-Disposition: form-data; name=\"asset[file]\"; filename=\"fabian-centeno-uY60pJUHqOo-unsplash.jpg\"\r\nContent-Type: image/jpeg\r\n">}}
  Maglev::Site Load (0.5ms)  SELECT "maglev_sites".* FROM "maglev_sites" ORDER BY "maglev_sites"."id" ASC LIMIT $1  [["LIMIT", 1]]
  TRANSACTION (1.3ms)  BEGIN
  Maglev::Asset Create (1.4ms)  INSERT INTO "maglev_assets" ("filename", "content_type", "width", "height", "byte_size", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"  [["filename", nil], ["content_type", nil], ["width", nil], ["height", nil], ["byte_size", nil], ["created_at", "2023-12-08 02:35:31.630188"], ["updated_at", "2023-12-08 02:35:31.630188"]]
  ActiveStorage::Attachment Load (2.1ms)  SELECT "active_storage_attachments".* 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", "Maglev::Asset"], ["name", "file"], ["LIMIT", 1]]
  ActiveStorage::Blob Create (1.6ms)  INSERT INTO "active_storage_blobs" ("key", "filename", "content_type", "metadata", "service_name", "byte_size", "checksum", "created_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id"  [["key", "002ab95u4hdex998jpobmw5cpc4u"], ["filename", "fabian-centeno-uY60pJUHqOo-unsplash.jpg"], ["content_type", "image/jpeg"], ["metadata", "{\"identified\":true}"], ["service_name", "local"], ["byte_size", 1583948], ["checksum", "f1y2gVRUElO71YtYCE0nZw=="], ["created_at", "2023-12-08 02:35:31.637841"]]
  ActiveStorage::Attachment Create (1.3ms)  INSERT INTO "active_storage_attachments" ("name", "record_type", "record_id", "blob_id", "created_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["name", "file"], ["record_type", "Maglev::Asset"], ["record_id", nil], ["blob_id", "89625400-95c5-42d7-9e8d-b91cb8fdf3b3"], ["created_at", "2023-12-08 02:35:31.640474"]]
  TRANSACTION (0.4ms)  ROLLBACK
Completed 500 Internal Server Error in 51ms (ActiveRecord: 20.4ms | Allocations: 38835)
`


ActiveRecord::NotNullViolation (PG::NotNullViolation: ERROR:  null value in column "record_id" of relation "active_storage_attachments" violates not-null constraint
DETAIL:  Failing row contains (4c6ed3a7-1022-467d-a048-1cc0e427e416, file, Maglev::Asset, null, 89625400-95c5-42d7-9e8d-b91cb8fdf3b3, 2023-12-08 02:35:31.640474).
):

About this issue

  • Original URL
  • State: closed
  • Created 7 months ago
  • Comments: 17 (6 by maintainers)

Most upvoted comments

@did i really do appreciate you digging into this, hopefully things will continue to work well for me atleast in the meantime. Maglev seems awesome so far.

ActiveStorage handles this well i think, if you want to take a look

# This migration comes from active_storage (originally 20170806125915)
class CreateActiveStorageTables < ActiveRecord::Migration[7.0]
  def change
    # Use Active Record's configured type for primary and foreign keys
    primary_key_type, foreign_key_type = primary_and_foreign_key_types

    create_table :active_storage_blobs, id: primary_key_type do |t|
      t.string   :key,          null: false
      t.string   :filename,     null: false
      t.string   :content_type
      t.text     :metadata
      t.string   :service_name, null: false
      t.bigint   :byte_size,    null: false
      t.string   :checksum

      if connection.supports_datetime_with_precision?
        t.datetime :created_at, precision: 6, null: false
      else
        t.datetime :created_at, null: false
      end

      t.index [ :key ], unique: true
    end

    create_table :active_storage_attachments, id: primary_key_type do |t|
      t.string     :name,     null: false
      t.references :record,   null: false, polymorphic: true, index: false, type: foreign_key_type
      t.references :blob,     null: false, type: foreign_key_type

      if connection.supports_datetime_with_precision?
        t.datetime :created_at, precision: 6, null: false
      else
        t.datetime :created_at, null: false
      end

      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

    create_table :active_storage_variant_records, id: primary_key_type do |t|
      t.belongs_to :blob, null: false, index: false, type: foreign_key_type
      t.string :variation_digest, null: false

      t.index [ :blob_id, :variation_digest ], name: :index_active_storage_variant_records_uniqueness, unique: true
      t.foreign_key :active_storage_blobs, column: :blob_id
    end
  end

  private
    def primary_and_foreign_key_types
      config = Rails.configuration.generators
      setting = config.options[config.orm][:primary_key_type]
      primary_key_type = setting || :primary_key
      foreign_key_type = setting || :bigint
      [primary_key_type, foreign_key_type]
    end
end

Ok i figured out part 1.

The maglev migrations / active storage do not work with uuids

For clarity, ive modified all the maglev migrations copied over to use uuids. This works fine now, uploads are fixed.

It might be worth looking at the migrations and changing to use the orm id generator types like active storage does.