0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

local環境のRailsでDynamoidを使ってみる

Last updated at Posted at 2025-02-13

この記事について

この記事は、local環境でRails・DynamoDB・ORMとしてDynamoidを使用してみた際のメモです。

さいごにでも書いてありますが、この記事はこれからも追記予定です。

前提

  • Docker/docker-composeを使用します
  • macOSでのみ動作確認を行なっています

環境構築

RailsとDynamoDBをdocker-composeで起動する

RailsとDynamoDBをlocal環境に構築するスクリプトを作成しました。このスクリプトを実行すると開発環境が立ち上がります。スクリプトの中では、docker-compose.ymlなどのファイルの生成、コンテナの立ち上げ、rails newなどを記述しています。

docker-compose.ymlの中身は、以下のとおりです。

docker-compose.yml
services:
  dynamo-demo-db:
    command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ./data"
    image: amazon/dynamodb-local:latest
    container_name: dynamo-local
    ports:
      - "8000:8000"
    volumes:
      - "./docker/dynamodb:/home/dynamodblocal/data"
    working_dir: /home/dynamodblocal
  app:
    build:
      context: .
      dockerfile: Dockerfile
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -b 0.0.0.0"
    volumes:
      - .:/app
    ports:
      - 3000:3000
volumes:
  dynamodb-data:
networks:
  default:
    name: dynamo-demo-network

DynamoDBをDockerで動かすにあたって、こちらを参考にしています。

Dynamoidを導入する

開発環境の準備ができたら、Gemfileに"aws-sdk-dynamodb""dynamoid"を追加します。

Gemfile
gem "aws-sdk-dynamodb"
gem "dynamoid"

bundle installを実行します。

% docker-compose exec app bundle install
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Fetching aws-eventstream 1.3.0
Fetching aws-partitions 1.1050.0
Fetching jmespath 1.6.2
Installing aws-eventstream 1.3.0
Fetching aws-sigv4 1.11.0
Installing aws-partitions 1.1050.0
Installing jmespath 1.6.2
Installing aws-sigv4 1.11.0
Fetching aws-sdk-core 3.218.1
Installing aws-sdk-core 3.218.1
Fetching aws-sdk-dynamodb 1.136.0
Installing aws-sdk-dynamodb 1.136.0
Fetching dynamoid 3.11.0
Installing dynamoid 3.11.0
Bundle complete! 20 Gemfile dependencies, 114 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
1 installed gem you directly depend on is looking for funding.
  Run `bundle fund` for details

initializerを定義します。

config/initializers/dynamoid.rb
Dynamoid.configure do |config|
  config.namespace = "dynamoid_demo"
  config.region = "us-east-1"
  config.access_key = "Dummy"
  config.secret_key = "Dummy"
  config.endpoint = "http://dynamo-demo-db:8000"
end

User modelを定義する

次に、DynamoDBに記録したいmodelを定義します。今回は、Userモデルを定義します。通常のRailsアプリケーションと異なり、ApplicationRecordを継承せず、Dynamoid::Documentincludeします。また、tableやfieldについても定義します。

app/models/user.rb
class User
  include Dynamoid::Document

  table name: :users, key: :id

  field :name, :string
end

rails consoleからUserモデルを操作してみる

User.create!

rails consoleでUser.create!をしてみます。実行すると以下のようにログが出力されました。

rails console
app(dev)> User.create!(name: 'first user')
[Aws::DynamoDB::Client 200 0.317321 0 retries] list_tables(exclusive_start_table_name:nil)  

(399.08 ms) LIST TABLES
(399.64 ms) CACHE TABLES
Creating dynamoid_demo_users table. This could take a while.
[Aws::DynamoDB::Client 200 0.059265 0 retries] create_table(table_name:"dynamoid_demo_users",key_schema:[{attribute_name:"id",key_type:"HASH"}],attribute_definitions:[{attribute_name:"id",attribute_type:"S"}],billing_mode:"PROVISIONED",provisioned_throughput:{read_capacity_units:100,write_capacity_units:20})  

(62.79 ms) CREATE TABLE
[Aws::DynamoDB::Client 200 0.03618 0 retries] put_item(table_name:"dynamoid_demo_users",item:{"name"=>{s:"first user"},"id"=>{s:"824bf1cd-5da9-42d0-87e6-aff658152fe6"},"created_at"=>{n:"1739450865.216913975"},"updated_at"=>{n:"1739450865.217141442"}},expected:{"id"=>{exists:false}})  

(39.91 ms) PUT ITEM - ["dynamoid_demo_users", {name: "first user", id: "824bf1cd-5da9-42d0-87e6-aff658152fe6", created_at: 0.1739450865216913975e10, updated_at: 0.1739450865217141442e10}, {}]
=> #<User id: "824bf1cd-5da9-42d0-87e6-aff658152fe6", name: "first user", created_at: Thu, 13 Feb 2025 12:47:45 +0000, updated_at: Thu, 13 Feb 2025 12:47:45 +0000>

Creating dynamoid_demo_users table と書かれたログがあります。このとき、create_tableが実行されており、存在しないtableを自動で作ってくれているようです。
また、CREATE TABLEが完了したあとにはput_itemが実行されています。

User.first

rails console
app(dev)> User.first
(0.19 ms) SCAN - ["dynamoid_demo_users", [{}]]
[Aws::DynamoDB::Client 200 0.077663 0 retries] describe_table(table_name:"dynamoid_demo_users")  

[Aws::DynamoDB::Client 200 0.033125 0 retries] scan(table_name:"dynamoid_demo_users",limit:1)  

=> #<User id: "824bf1cd-5da9-42d0-87e6-aff658152fe6", name: "first user", created_at: Thu, 13 Feb 2025 12:47:45 +0000, updated_at: Thu, 13 Feb 2025 12:47:45 +0000>

ActiveRecordと同様にUser.firstで先ほど作成したUserを取得できました。

field定義を追加する

Userモデルにage fieldを追加します。

app/models/user.rb
class User
  include Dynamoid::Document

  table name: :users, key: :id

  field :name, :string
+ field :age, :integer
end

fieldを追加したあと、User.craete!を実行するとageも一緒に記録できました。RDBみたいにmigrateを実行しなくてもスキーマを変更できるのは非常に便利ですね!

rails console
app(dev)> User.create!(name: 'second user', age: 10)
[Aws::DynamoDB::Client 200 0.03165 0 retries] put_item(table_name:"dynamoid_demo_users",item:{"name"=>{s:"second user"},"age"=>{n:"10"},"id"=>{s:"c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd"},"created_at"=>{n:"1739460583.365408009"},"updated_at"=>{n:"1739460583.366512404"}},expected:{"id"=>{exists:false}})  

(33.71 ms) PUT ITEM - ["dynamoid_demo_users", {name: "second user", age: 10, id: "c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd", created_at: 0.1739460583365408009e10, updated_at: 0.1739460583366512404e10}, {}]
=> #<User id: "c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd", name: "second user", age: 10, created_at: Thu, 13 Feb 2025 15:29:43 +0000, updated_at: Thu, 13 Feb 2025 15:29:43 +0000>

field定義を削除する

今度は逆に、Userモデルからage fieldを削除します。

app/models/user.rb
class User
  include Dynamoid::Document

  table name: :users, key: :id

  field :name, :string
- field :age, :integer
end

field定義を削除すると、以下のように、Userインスタンスの属性からageが消えていました。

rails console
app(dev)> User.find_by_id("c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd")
DEPRECATION WARNING: [Dynamoid] .find_by_id is deprecated! Call .find instead of (called from <main> at (app):60)
[Aws::DynamoDB::Client 200 0.033229 0 retries] get_item(table_name:"dynamoid_demo_users",key:{"id"=>{s:"c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd"}},consistent_read:nil)  

(36.62 ms) GET ITEM - ["dynamoid_demo_users", "c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd", {}]
=> #<User id: "c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd", name: "second user", created_at: Thu, 13 Feb 2025 15:29:43 +0000, updated_at: Thu, 13 Feb 2025 15:29:43 +0000>

また、ageを呼び出すとNoMethodErrorが発生しました。

rails console
app(dev)> User.find_by_id("c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd").age
DEPRECATION WARNING: [Dynamoid] .find_by_id is deprecated! Call .find instead of (called from <main> at (app):61)
[Aws::DynamoDB::Client 200 0.011879 0 retries] get_item(table_name:"dynamoid_demo_users",key:{"id"=>{s:"c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd"}},consistent_read:nil)  

(15.01 ms) GET ITEM - ["dynamoid_demo_users", "c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd", {}]
(app):61:in '<main>': undefined method 'age' for an instance of User (NoMethodError)

「field定義を削除 = テーブルからも削除されたのか?」と気になったので、再度field定義を追加します。

app/models/user.rb
class User
  include Dynamoid::Document

  table name: :users, key: :id

  field :name, :string
+ field :age, :integer
end

reload!してからUserインスタンスに対してageを呼び出すと、create!で指定していた10が返ってきました。

rails console
app(dev)> reload!
Reloading...
=> nil
app(dev)> User.find_by_id("c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd").age
DEPRECATION WARNING: [Dynamoid] .find_by_id is deprecated! Call .find instead of (called from <main> at (app):63)
[Aws::DynamoDB::Client 200 0.010293 0 retries] get_item(table_name:"dynamoid_demo_users",key:{"id"=>{s:"c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd"}},consistent_read:nil)  

(11.86 ms) GET ITEM - ["dynamoid_demo_users", "c0b4b075-7f7a-4ea5-8de0-f44d0de87dbd", {}]
=> 10

さいごに

ここまで、Dynamoidをつかってみたメモを残しました。もっとDynamoidを使う予定なので、わかったことがあればこの記事に追記します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?