Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Metadata about blobs stored with ActiveStorage with Rails 5+

We have been using rails 5.2RC1 for a couple weeks on a small number of production apps to test ActiveStorage. We've been able to get everything working with our Heroku instances (including PDF previews), but are now running into some questions around best practices.

Say we have the following model:

class Contract < ApplicationRecord
  has_many_attached :documents
end

This works perfectly.

However now we want to add some additional data about each individual document. Perhaps things like the type of document for the contract or some other type of metadata.

Our first thought was to try and stuff this into the metadata attribute of the blob, but that doesn't feel right.

The other thought that we had was to change the design to something like this:

class Contract < ApplicationRecord
  has_many :documents
end

class Document < ApplicationRecord
  belongs_to :contract
  has_many_attached  :files
end

Then using the document model to keep information about each attached file. Say in this example a contract has an original document, but then in the future there could be addendum attached to it that have their own unique properties that we would want to keep track of.

Thoughts?

like image 721
taylor01 Avatar asked Oct 23 '25 22:10

taylor01


1 Answers

At the time this question was asked, it's probably the case that metadata was getting overwritten as described in this Github issue. While metadata still isn't queryable (come on guys, nearly 5 years has passed), you can definitely add custom attributes.

The weird thing is that the attach() function param metadata says in the docs it is supposed to be a string, but that doesn't work and gets overwritten by the analyzer. If you just change it to an object-literal instead, that works and the custom metadata gets merged with the analyzer metadata.

So this works:

payment.archives.attach(
   io: File.open("./archive.zip"),
   filename: "archive.zip",
   content_type: "application/gzip",
   metadata: { customTag: "some value" }
)

But passing the metadata as a stringified object does not:

payment.archives.attach(
   io: File.open("./archive.zip"),
   filename: "archive.zip",
   content_type: "application/gzip",
   metadata: "{ \"customTag\": \"some value\" }"
)

Also, you can pass an ActionDispatch::Http::UploadedFile object as a param to io: which the docs also aren't clear on.. In my use case (and I imagine many others) I had an UploadedFile object coming from a multipart form request and needed to add some custom attributes to each file. hopefully this helps someone who is lost in legacy rails hell another 5 years from now.

like image 81
Trevor Bye Avatar answered Oct 25 '25 12:10

Trevor Bye