1

I am trying to complete this tutorial using version 2 of aws-sdk, I have included these extra gems

gem 'aws-sdk-core'

gem 'dotenv-rails', :groups => [:development, :test]

my .env file in the root folder is

S3_BUCKET=XXXredactedXXX
AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXredactedXXXXXX
AWS_SECRET_ACCESS_KEY=XXXXXredactedXXXXXX
AWS_REGION=Oregon

I am trying to test the configuration by running these commands in the rails console.

s3 = Aws::S3::Client.new
resp = s3.list_buckets
resp.buckets.map(&:name)
#=> ["bucket-1", "bucket-2", ...]

I assume the config in the .env file is working because without the AWS_REGION entry it threw this error

Aws::Errors::MissingRegionError: missing region; use :region option or export region name to ENV['AWS_REGION']

This 'resp = s3.list_buckets' command triggers this error 'Seahorse::Client::NetworkingError: getaddrinfo: Name or service not known'

The firewall ports are open

To                         Action      From
--                         ------      ----
80                         ALLOW       Anywhere
443                        ALLOW       Anywhere
53693                      ALLOW       Anywhere
8118                       ALLOW       Anywhere
21/tcp                     ALLOW       Anywhere
1863                       ALLOW       Anywhere
53                         ALLOW       Anywhere
3000                       ALLOW       Anywhere
80 (v6)                    ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)
53693 (v6)                 ALLOW       Anywhere (v6)
8118 (v6)                  ALLOW       Anywhere (v6)
21/tcp (v6)                ALLOW       Anywhere (v6)
1863 (v6)                  ALLOW       Anywhere (v6)
53 (v6)                    ALLOW       Anywhere (v6)
3000 (v6)                  ALLOW       Anywhere (v6)

The bucket log entry

XXXredactedXX my-first-bucket-tutorial985 [10/Mar/2015:06:31:51 +0000] 10.232.8.40 XXXredactedXX D37580D87A1D8EE9 REST.GET.NOTIFICATION - "GET /?notification HTTP/1.1" 200 - 115 - 15 - "-" "aws-internal/3" -

**Update, credentials set and working

Amazon have a ruby sample here and a number of credentials options here. There is a command line tool aws command line utility here. This tool creates a directory (.aws) with a credentials and a config file. This replaces the .env gem I believe because it serves the same purpose.

Credentials

[default]
aws_access_key_id = XXXXXredcatedXXX
aws_secret_access_key = XXXXXredactedXXXX

Config

[default]
#region = us-west-2
#output = json

As you can see the region is commented out and does not affect the ruby example because a region is supplied when the resource instance is created.

Gemfile

source 'https://rubygems.org'
gem 'aws-sdk', '~> 2.0.22'
gem 'uuid', '~> 2.3.7'

s3_sample.rb

# Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
#     http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

require 'rubygems'
require 'bundler/setup'
require 'aws-sdk'
require 'uuid'

s3 = Aws::S3::Resource.new(region: 'us-west-2')

uuid = UUID.new
bucket_name = "ruby-sdk-sample-#{uuid.generate}"
bucket = s3.bucket(bucket_name)
bucket.create

object = bucket.object('ruby_sample_key.txt')
object.put(body: "Hello World!")
Conor
  • 494
  • 6
  • 15

1 Answers1

1

finally I found a solution, this stackoverflow post with the additions for AWS

Set your credentials as before by creating a folder [.aws] in your root directory [~/], then create a Credentials and Config file with below contents

Credentials

[default]
aws_access_key_id = XXXXXredcatedXXX
aws_secret_access_key = XXXXXredactedXXXX

Config

[default]
#region = us-west-2
#output = json

Add these 2 gems to the generated Gemfile

gem 'carrierwave'
gem 'aws-sdk', '~> 2'

My amended PostsController, Carrierwave does have a method for determining the path to the file after the save but I couldnt get it working.

class PostsController < ApplicationController

  skip_before_action :verify_authenticity_token

  before_action :set_post, only: [:show, :edit, :update, :destroy]

  # GET /posts
  # GET /posts.json
  def index
    @posts = Post.all
  end

  # GET /posts/1
  # GET /posts/1.json
  def show

    @post_attachments = @post.post_attachments.all

  end

  # GET /posts/new
  def new

    @post = Post.new

    @post_attachment = @post.post_attachments.build

  end

  # GET /posts/1/edit
  def edit
  end

  # POST /posts
  # POST /posts.json
  def create

    s3 = Aws::S3::Resource.new(region: 'us-west-2')

    bucket = s3.bucket('my-first-bucket-tutorial1985')

    @post = Post.new(post_params)

    respond_to do |format|
      if @post.save
        params[:post_attachments]['avatar'].each do |a|

          @post_attachment = @post.post_attachments.create!(:avatar => a, :post_id => @post.id)

          File.open('public/uploads/post_attachment/avatar/' + "#{@post_attachment[:post_id]}" + '/'+ "#{@post_attachment[:avatar]}", 'rb') do |file|
            s3.bucket('my-first-bucket-tutorial985').object("#{@post_attachment[:avatar]}").put(body:file)
          end



        end

          format.html { redirect_to @post, notice: 'Post was successfully created.' }
       # format.json { render :show, status: :created, location: @post }
      else
        format.html { render :new }
       # format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /posts/1
  # PATCH/PUT /posts/1.json
  def update
    respond_to do |format|
      if @post.update(post_params)
        format.html { redirect_to @post, notice: 'Post was successfully updated.' }
        format.json { render :show, status: :ok, location: @post }
      else
        format.html { render :edit }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /posts/1
  # DELETE /posts/1.json
  def destroy
    @post.destroy
    respond_to do |format|
      format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def post_params
      params.require(:post).permit(:title, post_attachments_attributes: [:id, :post_id, :avatar])
    end
end

The proof it works

enter image description here

Community
  • 1
  • 1
Conor
  • 494
  • 6
  • 15