Dynamic DynamoDB has just been released in version 1.7.0. It contains a long list of goodies. But the major feature is the support for Global Secondary Indexes (GSI) in DynamoDB.

When it comes to provisioning, think of GSI just like regular tables. They have read and write capacity and can be scaled up and down just like tables. But it does not happen automatically when you change the provisioning of the table. However, Dynamic DynamoDB does now support automatic provisioning of GSIs.

Upgrading

Upgrade to the latest Dynamic DynamoDB using pip:

pip install -U dynamic-dynamodb

Configuration

GSI configuration works just as tables. You simply add a new section in your Dynamic DynamoDB configuration. Let’s say that you have a table configuration like this:

[table: ^blogPosts$]

To add a configuration for a GSI named myGSI in the blogPosts table, add a section like this:

[gsi: ^myGSI$ table: ^blogPosts$]

All configuration options work the same as for tables. Have a look in the DynamoDB GSI documentation for details. The example configuration does also cover GSI.

Attribution

Thanks to the AWS DynamoDB team for early access, testing and feedback during this release.

I was having trouble with updating a Global Secondary Index (GSI) in AWS DynamoDB. But I got this gist from @toastdriven to kick me in the right direction. Here’s how you do it with the boto.dynamodb2 library.

First off, make sure that you have the latest boto (at least 2.20.1) release, as it has support for DynamoDB GSI.

pip install -U boto

My table looks like this when described:

You can see that the table is called MailPostsExperimet and my only GSI is called gsiPosts. The GSI has a read/write provisioning of 1/1 initially. To increase the provisioning run:

That’s it!

I recently wanted to get the accessToken from the accounts-github package in Meteor to use in my own package. After writing a post on StackOverflow I learned to perform the following steps to access all GitHub user data in my client side code.

This all requires you to have the accounts-github package added to your project:

meteor add accounts-github

Then you simply extend the profile object for Meteor.user() as follows in your server-side code.

So, when the user is created we add accessToken, email and username in the MongoDB database.

The user data will now be accessible from the client-side code using Meteor.user().profile.github.accessToken.

Time and again I find myself in need of an extendable form where users can add rows to the form directly. I have found that the best and easiest solution for this is to use the exellent DataTables plugin for jQuery. I will show you a full example of a simple implementation of this in this blog post.

<head> section

Starting from the beginning. We need to make sure that we have the proper libraries available.

<head>
  <title>DataTables add/delete rows example</title>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
  <script src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
  <style media="screen" type="text/css">
  html {
    font-family: verdana, sans-serif;
  }
  </style>
</head>

We are adding jQuery just before DataTables as DataTables requires jQuery.

Control buttons

We’ll add some control buttons to the <body> tag.

<div id="controlButtons">
  <button onclick="addRow();">Add row</button>
  <button onclick="deleteRow();">Delete row</button>
</div>

Add the form table

Also in your <body> tag, please go ahead and add the actual table.

<form action="" method="POST">
  <table id="myTable">
    <thead>
      <tr>
        <th>First name</th>
        <th>Last name</th>
      </tr>
    </thead>
    <tbody>
    </tbody>
  </table>
  <input type="submit">
</form>

Take extra care in looking through the table structure. We started with giving the <table> an id set to myTable. This will be used as a reference to our table in the next step. Also, the table consists of a <thead> and <tbody>.

Write the JavaScript to bind it all together

Now, add the JavaScript below to the very end of your <body> tag. Take some time to read it through.

<script type="text/javascript">
  var count = 0;

  $(document).ready(function() {
    $('table#myTable').dataTable({
      'bFilter': false,
      'bInfo': false,
      'bPaginate': false,
    });

    // Add initial row
    addRow();
  } );

  function addRow() {
    $('table#myTable').dataTable().fnAddData( [
      '<input type="text" name="first_name_' + count + '">',
      '<input type="text" name="last_name_' + count + '">' ] );

    count++;
  }

  function deleteRow () {
    if (count != 1) {
        $("table#myTable").dataTable().fnDeleteRow(count - 1);

        count--;
    }
  }
</script>

So, what the JavaScript does is fairly straight forward. It

  • Initiates DataTables when the page has loaded
  • Defines a global function for adding rows
  • Defines a global function for removing rows

The initialization of DataTables is done within $(document).ready(). We tell DataTables which table to look for (table#myTable) and then we pass some configuration to remove functionality like pagination that is not wanted in a form context.

We are using two of DataTables methods to add and remove rows from the table. We use fnAddData() to add new rows to the table. It takes an array of fields/columns.

Metor JS does not come with support for routing (i.e. having separate pages) out-of-the-box. But it is easy to add that using the router smart package.

Install the router smart package

Assuming that you have Meteorite installed. Just run:

mrt add router

Configure routes in your client JavaScript

Update your client JavaScript code to also contain the following:

/**
* Routing
*/
Meteor.Router.add({
  '/example': 'my-example',
  '/': 'welcome',
  '*': '404'
});

Update your HTML template

Now, we do not want to render all templates every time the page is loaded. It’s easy to fix my updating your templates slightly with the renderPage function.

<head>
  <title>Example service</title>
</head>
<body>
  
  
</body>

<template name="menu">
  <div class="menu">
    <strong>Example Service</strong>
    <a href="/">Home</a>
    <a href="/example">Example page</a>
  </div>
</template>

<template name="welcome">
  <p>This is the start page</p>
</template>

<template name="my-example">
  <h1>My example</h1>
  <p>This is an example page</p>
</template>

<template name="404">
  <h1>Oops, page not found</h1>
  <p>The page you were looking for has gone missing!</p>
</template>

More features available

This is just a basic example of how to use the router smart package. Check out the project’s webpage for detailed documentation.