DynamoDB with Rails

Prerequisites

You must have Java installed to run dynamodb on Mac.

java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

Download the dynamodb server.

wget https://s3-us-west-2.amazonaws.com/dynamodb-local/dynamodb_local_latest.tar.gz

You can go to Setting Up DynamoDB Local (Downloadable Version) to find a link that is closest to your geographical location.

Extract the zip file:

tar -xvzf dynamodb_local_latest.tar.gz

Run this command to start the server from the directory where the zip file was extracted:

java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb

You can go through the tutorial that walks you through using Javascript SDK by going to http://localhost:8000/shell

Using DynamoDB with Rails

Create a new Rails project.

rails new dyno_app --skip-active-record

Add the aws-sdk gem to Gemfile.

gem 'aws-sdk'

Run bundle. You can connect to DynamoDB using Ruby aws-sdk as follows:

c = Aws::DynamoDB::Client.new(endpoint: "http://localhost:8000",region: "localhost")

List the Tables

c.list_tables

This gives the error:

Aws::Errors::MissingCredentialsError: unable to sign request without credentials set. Provide credentials to fix the problem.

Set the credentials.

Aws.config.update({
  region: 'localhost',
  credentials: Aws::Credentials.new('puff', 'daddy'),
  endpoint:'http://localhost:8000'
})

Response:

=> {:region=>"localhost", :credentials=>#<Aws::Credentials access_key_id="puff">, :endpoint=>"http://localhost:8000"} 
> c = Aws::DynamoDB::Client.new(endpoint: "http://localhost:8000",region: "localhost")
 => #<Aws::DynamoDB::Client> 
> c.list_tables
 => #<struct Aws::DynamoDB::Types::ListTablesOutput table_names=["Image", "ImageTag", "Tag"], last_evaluated_table_name=nil>

Scan the Tag Table

c.scan({table_name: 'Tag'})
resp.items #=> Array
resp.items[0] #=> Hash
resp.items[0]["AttributeName"] #=> <Hash,Array,String,Numeric,Boolean,IO,Set,nil>
resp.count #=> Integer
resp.scanned_count #=> Integer

The scanned_count is the number of items evaluated, before any ScanFilter is applied.

resp.items[0]
 => {"ImageCount"=>0.1e1, "Tag"=>"Amazon VPC"} 
 > resp.items[0]['ImageCount']
 => 0.1e1 
 > resp.items[0]['Tag']
 => "Amazon VPC" 

Getting Information about All Tables

dynamoDB = Aws::DynamoDB::Resource.new(region: 'localhost')

dynamoDB.tables.each do |t|
  puts "Name:    #{t.name}"
  puts "#Items:  #{t.item_count}"
end

Creating a Simple Table with a Single Primary Key

attribute_defs = [
  { attribute_name: 'ID',        attribute_type: 'N' },
  { attribute_name: 'FirstName', attribute_type: 'S' },
  { attribute_name: 'LastName',  attribute_type: 'S' }
]

key_schema = [
  { attribute_name: 'ID', key_type: 'HASH' }
]

index_schema = [
  { attribute_name: 'FirstName', key_type: 'HASH'  },
  { attribute_name: 'LastName',  key_type: 'RANGE' }
]

global_indexes = [{
  index_name:             'LastNameFirstNameIndex',
  key_schema:             index_schema,
  projection:             { projection_type: 'ALL' },
  provisioned_throughput: { read_capacity_units: 5, write_capacity_units: 10 }
}]

request = {
  attribute_definitions:    attribute_defs,
  table_name:               'Users',
  key_schema:               key_schema,
  global_secondary_indexes: global_indexes,
  provisioned_throughput:   { read_capacity_units: 5, write_capacity_units: 10 }
}

dynamodb_client = Aws::DynamoDB::Client.new(region: 'localhost')
dynamodb_client.create_table(request)
dynamodb_client.wait_until(:table_exists, table_name: 'Users')

Adding an Item to a Table

dynamoDB = Aws::DynamoDB::Resource.new(region: 'localhost')

table = dynamoDB.table('Users')

table.put_item({
  item:
    {
      "ID" => 123456,
      "FirstName" => 'Snoop',
      "LastName" => 'Doug'
}})

Getting Information about the Items in a Table

dynamoDB = Aws::DynamoDB::Resource.new(region: 'localhost')

table = dynamoDB.table('Tag')

scan_output = table.scan({
  limit: 50,
  select: "ALL_ATTRIBUTES"
})

scan_output.items.each do |item|
  keys = item.keys

  keys.each do |k|
    puts "#{k}: #{item[k]}"
  end
end

Getting Information about a Specific Item in a Table

dynamoDB = Aws::DynamoDB::Resource.new(region: 'localhost')

table = dynamoDB.table('Users')

resp = table.get_item({
  key: { 'ID' => 123456 }
})

first_name = resp.item['FirstName']
last_name = resp.item['LastName']

puts "First name: #{first_name}"
puts "Last name:  #{last_name}"

Updating a Table

dynamoDB = Aws::DynamoDB::Resource.new(region: 'localhost')

table = dynamoDB.table('Users')

Get the IDs of all of the users
resp = table.scan({ select: "ALL_ATTRIBUTES" })

resp.items.each do |item|
  id = item['ID']

  request = {
    key: { 'ID' => id },
    update_expression: 'set airmiles=:pVal',
    expression_attribute_values: { ':pVal' => '10000' }
  }

  # Update the item in the table:
  table.update_item(request)
end

References


Related Articles

Watch this Article as Screencast

You can watch this as a screencast DynamoDB with Rails


Ace the Technical Interview

  • Easily find the gaps in your knowledge
  • Get customized lessons based on where you are
  • Take consistent action everyday
  • Builtin accountability to keep you on track
  • You will solve bigger problems over time
  • Get the job of your dreams

Take the 30 Day Coding Skills Challenge

Gain confidence to attend the interview

No spam ever. Unsubscribe anytime.