RubyでLambdaからDynamoDBにデータ登録する

こんにちは!虎の穴ラボのNSSです。
最近はAlexaスキルやサーバーレスアプリケーションについて勉強しています。
今回はAWS LambdaからDynamoDBを利用する方法を紹介したいと思います。

1. ローカル開発環境構築

AWS サーバーレスアプリケーションモデル(AWS SAM)の開発環境を構築します。
AWS SAMはAWSでサーバーレスアプリケーションを構築するためのオープンソースフレームワークです。
ローカルでのサーバーレスアプリケーションの開発・テスト・デプロイをサポートしてくれます。
今回は、macOS上にAWS SAMの開発環境を構築していることを前提とします。

下記の公式にしたがって構築します。 python、pip、Dockerのインストールはご自身のPCの環境に応じて実施してください。

2. 処理の実装

処理を実装していきます。

2-1. サンプルアプリケーションの作成

sam init コマンドを実行するだけで、サンプルアプリケーションを作成することができます。

sam init -n ruby-sample -r ruby2.5

-nオプションは、サンプルアプリケーションを作成するディレクトリ名を設定できます。
-rオプションは使用するランタイムを設定します。
コマンドを実行すると以下のような一連のファイルが作成されます。

ruby-sample/
├── Gemfile
├── README.md
├── event.json
├── hello_world
│   ├── Gemfile
│   └── app.rb
├── template.yaml
└── tests
    └── unit
        └── test_handler.rb

2-2. Gemのインストール

Gemfileが2種類ありますが、"hello_world/Gemfile"に"aws-record"を追加します。

gem 'aws-record', '~> 2'

LambdaのRubyランタイムのバージョンは2.5なので、ローカルのRubyバージョンを2.5.0に変更します。

rbenv install 2.5.0 #インストールしていない場合
rbenv local 2.5.0

bundle installします。

bundle install --path vendor/bundle

2-2. ロジックの実装

手順1で生成された"hello_world/app.rb"の名称を変更します。 今回は"users/register_users.rb"とします。

ruby-sample/
└── users
    ├── Gemfile
    ├── Gemfile.lock
    ├── register_users.rb

Lambdaで受け取ったイベントを登録する処理を実装します。 DynamoDBにユーザーデータ登録を行い、正常終了したら200、失敗したら500を返します。

▼register_users.rb

require 'json'
require 'aws-record'

class User
  include Aws::Record
  set_table_name ENV['DDB_TABLE']
  string_attr :id, hash_key: true
  string_attr :name
  string_attr :sex
  string_attr :address
  string_attr :tel
end

def register(event:, context:)
  users = event["users"]
  begin
    users.each do |u|
      name = u["name"]
      sex = u["sex"]
      address = u["address"]
      tel = u["tel"]
      user = User.new(id: SecureRandom.uuid, name: name, sex: sex, address: address, tel: tel)
      user.save!
    end
  rescue => exception
    puts(exception.message)
    return create_response(500, "ユーザー登録が異常終了しました")
  end
  return create_response(200, "ユーザー登録が正常に終了しました")
end

def create_response(status, message)
  return {
    statusCode: status,
    body: {
      message: message,
    }.to_json
  }
end

2-3. テンプレートファイルの設定

テンプレートファイルはサーバーレスアプリケーションのトリガーとなるイベントや環境変数などを設定するファイルです。sam init で作成されたtemplate.yamlがテンプレートファイルにあたります。 DynamoDBの設定もここで行います。

▼template.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  AWS Lambda DynamoDB for Ruby

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3


Resources:

  RegisterUserFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: users/
      Handler: register_users.register
      Runtime: ruby2.5
      Policies:
      # DynamoDBへCreate/Read/Update/Deleteする権限を付与
      - DynamoDBCrudPolicy:
          TableName: !Ref UserDDBTable 
      # 環境変数の設定
      Environment:
        Variables:
          DDB_TABLE: !Ref UserDDBTable
  # DynamoDBテーブル設定
  UserDDBTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: id
        Type: String
Outputs:
  RegisterUserFunction:
    Description: "RubyAWSLambdaDynamoDB"
    Value: !GetAtt RegisterUserFunction.Arn

  RegisterUserFunctionIamRole:
    Description: "RegisterUserFunctionIAM Role"
    Value: !GetAtt RegisterUserFunctionRole.Arn

3. デプロイ

3-1. sam package

AWS SAMアプリケーションをパッケージ化します。

sam package --template-file template.yaml \
--output-template-file packaged-template.yaml \
--s3-bucket nss-lambda-sample
オプション 説明
template-file テンプレートファイルのパスを指定します
output-template-file パッケージ化後のテンプレートファイルのパスを指定します
s3-bucket パッケージをアップロードするS3バケットを指定します。

3-2. sam deploy

AWS SAMアプリケーションをデプロイします。

sam deploy  --template-file packaged-template.yaml \
--stack-name SampleStack \
--capabilities CAPABILITY_IAM
オプション 説明
template-file 3-1で作成したパッケージ化後のテンプレートファイルのパスを指定します
stack-name デプロイ先のAWS CloudFormationスタック名を指定します。新しいスタックを指定すると新規に作成されます。既存のスタックを指定した場合、スタックを更新します。
capabilities AWS Cloudformationが特定のスタックを作成する前に指定しなければならない機能のリストです。固定でCAPABILITY_IAMを設定します。

デプロイに成功するとAWS CloudFormationにスタックが登録されます。 AWS CloudFormationの詳しい説明は今回は省きます。 f:id:toranoana-lab:20190227171719p:plain

Lambdaコンソールを登録するとアプリケーションにスタックが登録されています。 f:id:toranoana-lab:20190227172116p:plain

4. 動作確認

Lambda コンソールを開き、テストを作成します。 以下のようなJSONオブジェクトを作成します。

{
  "users": [
    {
      "name": "田中太郎",
      "sex": "",
      "address": "埼玉県"
    },
    {
      "name": "山田一子",
      "sex": "",
      "address": "千葉県",
      "tel": "000-0000-0000"
    }
  ]
}

テストボタンを押して正常終了することを確認します。 f:id:toranoana-lab:20190227184118p:plain

DynamoDBのコンソールを開いてデータが登録されていることを確認します。 f:id:toranoana-lab:20190227184239p:plain

5. まとめ

今回はRuby環境でLambdaからDynamoDBにデータを登録する方法を紹介しました。
面倒なサーバーの設定や管理が一切必要なく、手軽にアプリケーションを作成できるので、
今後もAWS SAMを使用したサーバーレスアプリケーションを作成して、紹介していこうと思います。

P.S.

虎の穴ではRubyエンジニアをはじめとして一緒に働く仲間を絶賛募集中です! この記事を読んで、興味を持っていただけた方はぜひ弊社の採用情報をご覧下さい。

yumenosora.co.jp