Shrine dynamic buckets

Hi all

(Thank you all for your gem and your support on the forums etc. (I’m happy to make a PR if required, to improve the documentation, or the code etc. if required):

Perhaps I will describe my problem for context:

  1. I have an active record model: project.rb

  2. I would ideally like each project to have its own bucket. So when someone uploads a file to a new project, then that project’s bucket will have to be created, and the files will need to be uploaded to that new bucket.

I am following the tutorial given here:

My question is: does Shrine automatically create a bucket (or can it programmatically create one), or will I have to manually create a bucket and then make sure it properly resolves dynamically using the dyamic storage and default storage plugins?

Thank you for your help!

rgds

Ben

Hi, Shrine doesn’t create the S3 bucket for you, the S3 storage assumes an already created bucket and credentials.

I would recommend having a separate table for storing created buckets and their credentials. The default_storage could then generate a storage name with the ID of the created bucket record, so that with dynamic_storage plugin you could then extract the ID from the name of the storage and retrieve the bucket record.

Here is a CLI I wrote for myself to help me reproduce issues with Shrine. Hopefully it can help with implementing programmatic bucket creation with bucket-specific credentials.

Thank you for your ideas!

Hi Janko

Returned to this and finally got it working. Here is the code:

  Shrine.plugin :default_storage, store: -> {
    record.bucket_name
  }

  Shrine.plugin :dynamic_storage

  Shrine.storage StorageWrapper.bucket_regex do |match|
    Shrine::Storage::GoogleCloudStorage.new(project: Chamber.env.google.project_name, bucket: StorageWrapper.full_bucket_name(match[1]), prefix: "store", credentials: credentials)
  end

Question: where do you recommend that this code goes? I’ve notied when I place it inside my FileUploader.rb class, i’m getting a very funny error: TypeError (no implicit conversion of nil into Hash) and this error disappears when I place the above code in the initialer. Was wanting to know where you would typically add this code?

rgds

Ben

Hi Ben,

If you want this setting to be applied to all uploaders, you’d put it into an initializer, otherwise you’d configure it on the uploader level (you can look at the Shrine class here as a “base uploader”). You’d do this by removing Shrine. from your calls:

class MyUploader < Shrine
  plugin :default_storage, ...
  plugin :dynamic_storage
  storage ...
end
1 Like

Thank you Janko, for clearing that up. I will follow your advice.