Question

Retrieve image from Space AWS S3 ERROR

Hi everyone,

I have a rails application that allows users to upload an image and then this image is uploaded to IPFS. We are using ActiveStorage and storing the image in a local folder.

To go to production I have decided to try Space by Digital Ocean.

The file is uploading correctly to Space, but when I want to upload it to IPFS I get an error because the image is no longer stored locally.

I got the following error. It’s because now I’m using “S3” service instead of “Disk”

ERROR: undefined method `path_for' for #<ActiveStorage::Service::S3Service:0x000055691f1484c0>

We’re getting the error in this function

    def upload(collection)
      attachment = collection.attachment
      file_path = ActiveStorage::Blob.service.send(:path_for, attachment.key)
      content_type = attachment.blob.content_type
      file_io = Faraday::UploadIO.new(file_path, content_type)
      ok, image_ipfs_hash = send_file(file_io)
      return unless ok
      metadata = {
        name: collection.name,
        description: collection.description,
        image: 'https://ipfs.io/ipfs/' + image_ipfs_hash
      }
      File.write("tmp/metadata.json", metadata.to_json)
      metadata_io = Faraday::UploadIO.new("tmp/metadata.json", 'application/json')
      ok, metadata_ipfs_hash = send_file(metadata_io)
      collection.update(image_hash: image_ipfs_hash, metadata_hash: metadata_ipfs_hash)
      ok ? metadata_ipfs_hash : nil
    end

upload function is being called by create function

  def create
    begin
        @collection = Collection.new(collection_params)
        @collection.state = :pending
        @collection.address = Collection.generate_uniq_token
        @collection.creator_id = current_user.id
        @collection.owner_id = current_user.id
        @collection.data = JSON.parse(collection_params[:data]) if collection_params[:data].present?
        @collection.owned_tokens = @collection.no_of_copies
        if @collection.valid?
          @collection.save
          @metadata_hash = Api::Pinata.new.upload(@collection)
        else
          @errors = @collection.errors.full_messages
        end
    rescue Exception => e
      Rails.logger.warn "################## Exception while creating collection ##################"
      Rails.logger.warn "ERROR: #{e.message}, PARAMS: #{params.inspect}"
      Rails.logger.warn $!.backtrace[0..20].join("\n")
      @errors = e.message
    end
  end

The storage.yml looks like

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>
  
digitalocean:
  service: "s3"
  endpoint: "https://nyc3.digitaloceanspaces.com/"
  access_key_id: <%= Rails.application.credentials.dig(:digitalocean, :access_key) %>
  secret_access_key: <%= Rails.application.credentials.dig(:digitalocean, :secret) %>
  bucket: "stg-vikuimages"
  region: "nyc3"

I was trying to retrieve the image from the Space using AWS S3. I added the following code within the create function

 s3 = Aws::S3::Client.new
 resp = s3.get_object(bucket: 'stg-vikuimages', key: attachment.key)
 respBody = resp.body

I’m getting this error even though I set the region as it’s shown in the file storage.yml

ERROR: No region was provided. Configure the `:region` option or export the region name to ENV['AWS_REGION']

I have almost no experience with rails. That is why I require your help.

Regards!


Submit an answer

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer