何かやってみるブログ

興味をもったことに関して書いています。技術系の記事が多いです。

Ruby on Jets入門してみた (DynamoDBを使うパターン ローカルで動かすまで)

www.takayasugiyama.com

前回の記事をRDSを使ったJetsをデプロイするところまで試したので、今回はDynamoDBを使うパターンを試してみたいと思います。

そもそもDynamoDBとは

AWSが提供するNoSQLのデータベースです。詳しくは以下の記事を参照してください。

dev.classmethod.jp

dynamodb-localdynamodb-adminをインストールする

下記の記事を参考にインストールしていきます。 github.com

dynamodb-localはローカルでDynamoDBを使うためにインストールします。

$ brew cask install dynamodb-local

dynamodb-adminをインスールするとブラウザ上でDynamoDBの状態を確認できるのインストールします。

$  npm install -g dynamodb-admin

github.com

dynamodb-localとdynamodb-adminを起動して動作を確認する

dynamodb-localを動かすためにはjavaが必要なので、javaが入っていない場合はインストールします。

$ brew cask install adoptopenjdk
$ java --version 
$ dynamodb-local
Initializing DynamoDB Local with the following configuration:
Port:   8000
InMemory:   false
DbPath: null
SharedDb:   false
shouldDelayTransientStatuses:   false
CorsParams: *

dynamodb-localを実行すると8000番ポートで立ち上がります。

$ dynamodb-admin

dynamodb-adminを実行すると8001番ポートで立ち上がります。

http://localhost:8001 にアクセスして管理画面が表示されればOKです。

f:id:s-takaya1027:20200613111834p:plain

プロジェクトの作成

以下の環境で試してみました。

  • ruby 2.5.0
  • jets 2.3.16
$  jets new dynamodb-jets

マイグレーションファイルの作成と実行

$  jets dynamodb:generate create_posts
$ jets dynamodb:migrate ./dynamodb/migrate/20200613114302-create_posts_migration.rb

http://localhost:8001 にアクセスしてみるとテーブルが作成されていることが確認できました。

f:id:s-takaya1027:20200613114746p:plain

Scaffoldの実行

$ jets g scaffold Post title:string --no-migration

Scaffoldの修正

jetsではDynamoDBに接続するモデルにはdynomiteというORMのgemを使っているので、それゆえにActiveRecordを使用する型式からの変更が必要です。

github.com

READMEに書いてあるように変更していきます。

class Post < ApplicationItem
  extend ActiveModel::Naming
  include ActiveModel::Validations

  def persisted?
    !self.id.nil?
  end


  column :id, :content, :created_at, :updated_at
  validates :content, presence: true
end

デフォルトの場合、ActiveModelの機能が使えなかったりバリデーションが使えなかったりするのでライブラリを追加しています。

railsguides.jp

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :delete]

  # GET /posts
  def index
    @posts = Post.scan
  end

  # GET /posts/1
  def show
  end

  # GET /posts/new
  def new
    @post = Post.new
  end

  # GET /posts/1/edit
  def edit
  end

  # POST /posts
  def create
    @post = Post.new
  
    if @post.replace(post_params)
      redirect_to post_path(@post.id)
    else
      render :new
    end
  end

  # PUT /posts/1
  def update
    if @post.replace(post_params)
      redirect_to  post_path(@post.id)
    else
      render :edit
    end
  end

  # DELETE /posts/1
  def delete
    Post.delete(@post.id)
    if request.xhr?
      render json: {success: true}
    else
      redirect_to posts_path
    end
  end

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

  def post_params
    params.require(:post).permit(:content).to_h
  end
end

Jetsの仕様でlink_toメソッドの第2引数は文字列のみ受け取るという仕様のため、修正する必要があるので修正していきます。

<h1>Posts</h1>

<table>
  <thead>
    <tr>
      <th>Content</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @posts.each do |post| %>
      <tr class="jets-element-to-delete">
        <td><%= post.content %></td>
        <td><%= link_to 'Show', "/posts/#{post.id}" %></td>
        <td><%= link_to 'Edit', "/posts/#{post.id}/edit" %></td>
        <td><%= link_to 'Destroy',"posts/#{post.id}", method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Post', new_post_path %>
<%= form_with(model: post, local: true, url: url, method: method) do |form| %>
  <% if post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>
        <% post.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :content %>
    <%= form.text_field :content %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>
<h1>New Post</h1>

<%= render 'form', post: Post.new, url: posts_path, method: :post %>

<%= link_to 'Back', posts_path %>
<h1>Editing Post</h1>

<%= render 'form', post: @post, url: "/posts/#{@post.id}", method: :patch %>

<%= link_to 'Show', "/posts/#{@post.id}" %> |
<%= link_to 'Back', posts_path %>
<p>
  <strong>Content:</strong>
  <%= @post.content %>
</p>

<%= link_to 'Edit', edit_post_path(@post.id) %> |
<%= link_to 'Back', posts_path %>

動作確認

CURD機能を試しながら http://localhost:8001 の管理画面でデータが作成、更新、削除されていることが確認できました。

作成

f:id:s-takaya1027:20200613135555p:plain

更新

f:id:s-takaya1027:20200613135707p:plain

削除

f:id:s-takaya1027:20200613135749p:plain