# Active Storage set blob key on direct upload (changelog)

**URL:** <https://discuss.rubyonrails.org/t/active-storage-set-blob-key-on-direct-upload-changelog/76078>\
**Category:** rubyonrails-talk\
**Tags:** activestorage\
**Created:** [August 20, 2020, 2:09pm UTC](https://discuss.rubyonrails.org/t/active-storage-set-blob-key-on-direct-upload-changelog/76078 "2020-08-20T14:09:31Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![leenyburger](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/leenyburger/32/1710_2.png) [@leenyburger](https://discuss.rubyonrails.org/u/leenyburger)\
**Post date:** [August 20, 2020, 2:09pm UTC](https://discuss.rubyonrails.org/t/active-storage-set-blob-key-on-direct-upload-changelog/76078/1 "2020-08-20T14:09:31Z")

</div>

Referencing this PR: [https://github.com/rails/rails/commit/4dba136c83cc808282625c0d5b195ce5e0bbaa68](https://github.com/rails/rails/commit/4dba136c83cc808282625c0d5b195ce5e0bbaa68) We can now specify a blob key when using the traditional `attach` method. However, I cannot figure out how to specify the key when using direct uploads. The direct upload method was also updated in this PR, so I’m hoping I’m missing something.

As far as I can tell, if I want to send in a custom key such as `user.company/public/filename` using direct uploads I…can’t? I’d have to hook in here: [https://github.com/rails/rails/blob/b5dac96b59a582c7968b0c33d6ff39d1cfc336dc/activestorage/app/assets/javascripts/activestorage.js#L690](https://github.com/rails/rails/blob/b5dac96b59a582c7968b0c33d6ff39d1cfc336dc/activestorage/app/assets/javascripts/activestorage.js#L690)`var blob = new BlobRecord(_this.file, checksum, _this.url);` Even if I send in a `this.key` to my direct uploads controller, I don’t want to change the call to BlobRecord and I don’t want to patch activestorage.js b/c that will certainly cause trouble in the future.

I can override `key` in `blob.rb`, but I want to prefix based on user.company, so I need to send in the user details somehow.

TLDR: Can I send a `key` variable with this new PR via direct uploads? I know this was previously not how ASt was designed, but the above PR makes me hopeful there may be a way.

---

<div class="post-metadata">

**Author:** ![leenyburger](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/leenyburger/32/1710_2.png) [@leenyburger](https://discuss.rubyonrails.org/u/leenyburger)\
**Post date:** [September 29, 2020, 2:13am UTC](https://discuss.rubyonrails.org/t/active-storage-set-blob-key-on-direct-upload-changelog/76078/2 "2020-09-29T02:13:38Z")

</div>

Note: On Rails 6.0   
I’ve sorted out that to enable changing the key on direct uploads you can’t just override `key` on `blob.rb` because the key is being set _before_`def key` is called. By the time you hit the `def key` method `self[:key]` has already been set by `generate_unique_secure_token` which IIRC is called from activerecord. Anyway, since I’m only using direct uploads I patched `create_before_direct_upload!` to force the key in the format I want.

```ruby
    def create_before_direct_upload!(filename:, byte_size:, checksum:, content_type: nil, metadata: nil)
      key = SecureRandom.base36(28) + "/" + filename
      create! key: key, filename: filename, byte_size: byte_size, checksum: checksum, content_type: content_type, metadata: metadata
    end

```

Would love to hear any other ideas.

---

<div class="post-metadata">

**Author:** ![arian](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/arian/32/14006_2.png) [@arian](https://discuss.rubyonrails.org/u/arian)\
**Post date:** [September 30, 2021, 9:10am UTC](https://discuss.rubyonrails.org/t/active-storage-set-blob-key-on-direct-upload-changelog/76078/3 "2021-09-30T09:10:32Z")

</div>

This applies for Rails 6.1:

ActiveRecord now has a thing called `has_secure_token`, which ActiveStorage is using on Blob. This `has_secure_token` is setting a `before_create` with the following code:

```ruby
before_create { send("#{attribute}=", self.class.generate_unique_secure_token(length: length)) unless send("#{attribute}?") }

```

This in turn sets `self[:key]` to be a secure\_token

When it’s being called like this, the `self[:key]` method only sets it if it doesn’t exist

```ruby
ActiveStorage::Blob.class_eval do
  def key
    self[:key] ||= 'your custom key'
  end
end

```

I fixed this by doing the following in `config/application.rb`

```ruby
class Application < Rails::Application
  # ...
  # ...
  # ...

  Rails.application.config.to_prepare do
    require 'active_storage/blob'
    class ActiveStorage::Blob
      def self.generate_unique_secure_token(length: MINIMUM_TOKEN_LENGTH)
        gust = SecureRandom.base36(length)
        epoch = Time.now.to_i.to_s
        checksum = Digest::MD5.hexdigest(gust + epoch)

        folder = checksum.chars.first(9).each_slice(3).to_a.map(&:join).join('/')

        "#{folder}/#{gust}"
      end
    end

    # Rails 5 doesn't have secure_token for Blob, so this will monkey patch it
    ActiveStorage::Blob.class_eval do
      def key
        self[:key] ||= generate_key_with_folder
      end

      def generate_key_with_folder
        gust = self.class.generate_unique_secure_token
        epoch = Time.now.to_i.to_s
        checksum = Digest::MD5.hexdigest(gust + epoch)

        folder = checksum.chars.first(9).each_slice(3).to_a.map(&:join).join('/')

        "#{folder}/#{gust}"
      end
    end
  end
end

```

---

<div class="post-metadata">

**Author:** ![IrisFM](https://avatars.discourse-cdn.com/v4/letter/i/f14d63/32.png) [@IrisFM](https://discuss.rubyonrails.org/u/IrisFM)\
**Post date:** [March 20, 2023, 8:55pm UTC](https://discuss.rubyonrails.org/t/active-storage-set-blob-key-on-direct-upload-changelog/76078/4 "2023-03-20T20:55:11Z")

</div>

Is this still the best solution? Or is there something simpler now?

I’d love to just send a key name in the js.

---

<div class="post-metadata">

**Author:** ![Roman123456789](https://avatars.discourse-cdn.com/v4/letter/r/6a8cbe/32.png) [@Roman123456789](https://discuss.rubyonrails.org/u/Roman123456789)\
**Post date:** [March 22, 2023, 8:23am UTC](https://discuss.rubyonrails.org/t/active-storage-set-blob-key-on-direct-upload-changelog/76078/5 "2023-03-22T08:23:00Z")

</div>

Yes, there are already easier solutions. But for this, it is better to contact the Ruby on rails developers in [Factor Dedicated Teams](https://factordedicatedteams.com/hire-dedicated-ruby-on-rails-developer/). I work with them myself.
