arrow githublightnings linkedinlock target triangle-icon twitter

Managing Remote Resources in Ruby Using Azure Storage Library

Meritxell
September 05, 2018

Last week I faced a very interesting challenge at work which I’d like to share with you. The situation is probably just a corner case, however it’s worth explaining.

Let’s say we were providing a solution that maintains updated information about restaurants in the cloud.

Our interface would allow users to create files with information about each restaurant and store them in a remote storage, so other clients could read that information.

The generated file would look like this:

# super_tasty.yml

super_tasty:
    address: ‘banana street, 34’
    phone: 555987623

Then we were using Carrierwave along with carrierwave-azure_rm gem to be able to store files in Azure remote storage:

#Gemfile

gem ‘carrierwave’
gem ‘carrierwave-azure_rm’
# config/initializers/carrierwave.rb

CarrierWave.configure do |config|
    config.storage = :azure_rm
config.azure_storage_account_name = ‘my_account_name’
config.azure_storage_access_key = ‘my_super_secret_key’
config.azure_container = ‘my_azure_container’
end

In the service, we were writing the content to a file and calling the uploader:

# app/services/warehouse.rb

def persist_remote
    # ...
uploader = FilesUploader.new
uploader.store!(file)
end

Which would finally upload the file through Carrierwave:

# app/uploaders/files_uploader.rb

class FilesUploader < CarrierWave::Uploader::Base
    # ...
end

This worked correctly so far.

But after a while, we realised we also needed a system that could remove outdated files from the cloud. As we couldn’t find a way to make Carrierwave do this, we decided to start using Azure blob service, for which Microsoft provides the azure-storage-blob gem:

#Gemfile

gem azure-storage-blob

Used in the service:

#app/service/warehouse.rb

def remove_remote
    service.delete_blob(
        ‘my_azure_container’,
        “path/to/#{restaurant.name}.yml”
)
end

private

def service
      @service ||= Azure::Storage::Blob::BlobService.create(
        storage_access_key: ‘my_super_secret_key’,
        storage_account_name: ‘my_account_name’
      )
end

This was also working fine, but suddenly file upload was not working anymore! After some research, we realised that this gem interferes somehow with Carrierwave’s dependencies, making it stop working and producing a regression problem!

We were not able to use both gems together, but Azure blob service was able to upload files, so we decided to put aside Carrierwave and rewrite this functionality:

# app/services/warehouse.rb

def persist_remote
      service.create_block_blob(
        ‘my_azure_container’,
        “path/to/#{restaurant.name}.yml”,
        yamelized_content
      )
end

This solved our issue and allowed us to centralize the interaction with remote storage in a very simple way.

I’m quite proud of how we solved this issue.

On one hand, because we came out with a more consistent way of managing remote resources. We did this by sticking to Azure blob service all the time instead of using an Uploader for some operations.

On the other hand, because we learned how to use Azure blob service. Ideally, I’d like the documentation to be more straightforward, as it is a bit convoluted to find this gem from Microsoft’s Ruby Developer Center. However, once you’ve get into it, the usage instructions are very descriptive.

Microsoft also provides gems for other operations on Azure, which can be found here.

Articles

By using this website you agree to our cookie policy
x