[Ruby on Rails]Dynamoidを使ってAmazon DynamoDBと接続する
Dynamoidとは
DynamoidはRailsの中でActiveRecordのようにDynamoDBと連携できるORM(Object-Relational Mapper)ODM(Object Document Mapper)です(追記: 公式にはORMと書かれているため、本記事もORMに訂正いたします。)もともとRubyのaws-sdkにはAWS::Record::HashModel
というORMがあり、弊社ブログでも紹介されていますが、aws-sdkのv2では削除されてしまった(?)ようなので、代わりに見つけたDynamoidというgemを試してみました。(ただ、後で分かった事ですが、Dynamoidもaws-sdkのv1に依存していました。)
The Ruby Toolboxを見る限りでは、 現時点で他に有力なDynamoDBのORMは無さそうです。(知っていたらコッソリ教えてください。)。ちなみに2位のFakeDynamoはローカルで動作するDynamoDBのエミュレータだそうです。
サンプルアプリ
今回作成するサンプルアプリは、以下の記事を参考にします。
Railsのセットアップ
ActiveRecordは使わないので-Oオプションでインストールしないようにします。
インストールしてしまうと、ActiveRecordがデータベースのアダプタを探そうとしてエラーになります。
mkdir my-simple-todos && cd my-simple-todos bundle init vim Gemfile # gem 'rails' をコメントアウトする bundle install bundle exec rails new . -O --skip-bundle # ActiveRecordは使わない
次に必要なgemをインストールします。
冒頭でも書きましたが、dynamoidはaws-sdkはv1にしか対応していないので'~> 1.0'を指定します。
Gemfile
gem 'aws-sdk', '~> 1.0' gem 'dynamoid' gem 'bootstrap-sass'
bundle install
設定
AWSのアクセスキーとDynamoDBのエンドポイントを設定します。
config/aws.yml
development: access_key_id: YOUR_ACCESS_KEY_ID secret_access_key: YOUR_SECRET_ACCESS_KEY dynamo_db_endpoint: "dynamodb.ap-northeast-1.amazonaws.com"
dynamoidの設定を書きます。
- namespaceがテーブル名の接頭語になります。Rails.env + namespaceとすることで環境ごとにテーブルを分けられます。
- partitioningはfalseにしておきます。
config/initializer/dynamoid.rb
Dynamoid.configure do |config| config.adapter = 'aws_sdk' # This adapter establishes a connection to the DynamoDB servers using Amazon's own AWS gem. config.namespace = "dynamoid_app_development" # To namespace tables created by Dynamoid from other tables you might have. config.warn_on_scan = true # Output a warning to the logger when you perform a scan rather than a query on a table. config.partitioning = false # Spread writes randomly across the database. See "partitioning" below for more. config.partition_size = 1 # Determine the key space size that writes are randomly spread across. config.read_capacity = 1 # Read capacity for your tables config.write_capacity = 1 # Write capacity for your tables end
ちなみにですが、DynamoDB Localはaws-sdkのv1に対応していないため、Dynamoidと合わせて使うことはできませんでした。
DynamoDB Local does not support v1 API. (AWS::DynamoDB::Errors::InvalidAction)
Model
Dynamoid::Documentをincludeします。ActiveRecordは継承しませんのでご注意ください。
keyにはDynamoDBで設定したハッシュキー名を指定します。
app/model/task.rb
class Task include Dynamoid::Document table name: :tasks, key: :id // テーブル名とkeyを指定 field :name, :string // Stringのフィールド field :timestamps, :datetime // datetimeのフィールド end
Controller
サンプルをそのまま使わせてもらいます。
app/controller/tasks.rb
class TasksController < ApplicationController def index @tasks = Task.all.sort{ |a, b| a.created_at <=> b.created_at } end def create task = Task.new(params[:task]) task.save redirect_to :back, notice: 'Created New Task.' end def destroy task = Task.find_by_id(params[:id]) task.delete redirect_to :back, notice: 'Deleted Task.' end end
View
サンプルをそのまま使わせてもらいます。
app/views/tasks/index.html.erb
<div class="container"> <h1>MyTasks</h1> <!-- 操作が成功したときに表示する --> <% if notice %> <p class="alert alert-success"><%= notice %></p> <% end %> <!-- 操作が失敗したときに表示する --> <% if alert %> <p class="alert alert-error"><%= alert %></p> <% end %> <!-- 入力フォーム --> <div><%= form_tag({:controller => :tasks, :action => :create}, {:class => "input-append"}) do %> <%= text_field_tag "task[name]", "", :id => "task_name" %> <%= submit_tag "ADD", :class => "btn" %> <% end %></div> <!-- アイテム一覧 --> <div><% @tasks.each do |task| %><% end %> <table class="table table-striped table-bordered"> <tbody> <tr> <th>Name</th> <th>CreatedAt</th> <th>UpdatedAt</th> <th>Done</th> </tr> <tr> <td><%= task.name %></td> <td class="span3"><%= task.created_at.strftime('%Y/%m/%d %H:%M:%S') %></td> <td class="span3"><%= task.updated_at.strftime('%Y/%m/%d %H:%M:%S') %></td> <td class="span1"><%= button_to 'Done', { :action => "destroy", :id => task.id }, method: :delete, class: 'btn btn-small btn-primary' %></td> </tr> </tbody> </table> </div> </div>
Routing
サンプルをそのまま使わせてもらいます。
config/routes.rb
resources :tasks, only: [:index, :create, :destroy]
Asset
Bootstrapを有効にするために以下を追加します。
app/assets/stylesheets/application.scss ※.cssしかない場合は、.scssに変更します
@import "bootstrap-sprockets"; @import "bootstrap";
app/assets/javascripts/application.js
//= require bootstrap-sprockets
DynamoDB
テーブルは自動で作成されたりはしませんので、事前にテーブルを作っておきます。
- テーブル名: dynamoid_app_development_tasks
- プライマリインデックス(ハッシュキー): id
動作確認
Railsを起動します。
bundle exec rails s
localhost:3000/tasks
AWSコンソールでDynamoDBにデータが書き込み/削除ができることが確認できました。
まとめと所感
本エントリーではDynamoidのインストールと基本的な動作まで確認しました。Dynamoidのドキュメントを見ると他にもAssociationsやValidations、Callbacksなど基本的なことはできるようですが、あまり開発が活発ではないことと、aws-sdkのv1に依存するということで、本格的に使うには不安要素が大きいと感じました。