Ruby
DynamoDB

DynamoDBのためのdinamoという簡易的なORMをかいた

More than 1 year has passed since last update.

先日書いた記事の中で触れていたDynamoDBのための簡易的なORMについて、随分前から公開はしているものの、せっかくなので記事を書いて紹介しようと思い立った。

https://github.com/namusyaka/dinamo

位置付けとしては件のメディアストレージ基盤を開発する過程でうまれた副産物的なもの。
名前はDynamoをイタリア語にしただけで、読み方は「ディナモ」。

使い方

Ruby界隈でよく見られるORMの振る舞いを踏襲している、というだけでは些か抽象的すぎるので、具体例をいくつか示したい。

モデルを定義する

class User < Dinamo::Model
  hash_key :name, type: :string
  field :ruby, type: :string
end

オブジェクトを生成する/保存する

user = User.new(name: 'numb', ruby: 'なんぶ')
user.persisted? #=> false
user.save
user.persisted? #=> true

createを使っても良い。

user = User.create(name: 'numb', ruby: 'なんぶ')
user.persisted? #=> true

オブジェクトを変更する

user = User.new(name: 'numb', ruby: 'なんぶ')
user.changed? #=> false
user.name = 'なんぶ'
user.changed? #=> true
user.save
user.changed? #=> false

オブジェクトを取得する

user = User.create(name: 'numb', ruby: 'なんぶ')
User.get(name: 'numb') #=> #<User:...>

オブジェクトを削除する

user = User.create(name: 'numb', ruby: 'なんぶ') #=> <User:...>
user.destroyed? #=> false
user.destroy
user.destroyed? #=> true

バリデーション

デフォルトではvalidates_presence_ofのみが動作する。
基本的にバリデーターは自分で実装し、validates_withを用いて追加する。

class NameLengthValidator < Dinamo::Model::Validation::Validator
  def validate(record)
    unless options[:length].include?(record.name.length)
      record.errors.add(:name, I18n.t("models.user.error.length"))
    end
  end
end

class User < Dinamo::Model

  hash_key :id
  field :name, type: :string

  validates_with NameLengthValidator, length: 1..30

end

コード中にあるDinamo::Model::Validation::Validatorなど(EachValidatorもある)を継承することで容易にバリデータを実装できる。

例外機構

savecreateupdateにはそれぞれ!を末尾に加えたメソッドも用意されており、該当するレコードが存在しなかったり、バリデーション違反とされた場合に例外が発生するようになる。

なぜ作ったか

件のメディアストレージ基盤を開発する段階では、DynamoDB向けのORMは観測範囲においてはdynamoidくらいしか見つからなかった。
ところがdynamoidはaws-sdk v2には対応しておらず、選択肢から除外せざるを得なかったという経緯がある。

観測範囲内に無いものは作るほかないので、ある程度自分からして扱いやすいインターフェースを備えたORMを書いた結果がdinamoだ。

所感

DynamoDBは使い勝手がいいが、aws-sdk単体で叩き続けるのはさすがに骨が折れる作業だ。
今回かいたdinamoについては、シンプルにDynamoDBを使う分には便利なgemになったように思う。

アソシエーションやマイグレーションといった機構については実装していない。
そもそも必要性について懐疑的であるし、加えて自分にとっては現状必要なものではなかったのが大きいように思う。

追記

という記事をあたためていたら、dynamoidがaws-sdk v2に対応したようだ。
リッチに、かつ、より楽にDynamoDBを使いたいRubyエンジニアはdynamoidを使うといいかもしれない。