Journey

技術に関することと覚書と

HanamiのEntityのschemaに別Entityを使用する方法

結論

class User < Hanami::Entity
  attributes do
    # one
    attribute :post, Types::Entity(Post)

    # many
    attribute :posts, Types::Collection(Post)
  end
end

経緯

HanamiでDDDっぽく書くために https://guides.hanamirb.org/entities/custom-schema/ に書いてあるとおりに、厳密に属性のチェックをしていました。

class User < Hanami::Entity
  attributes do
    attribute :id, Types::String
    attribute :name, Types::String

    attribute :created_at, Types::DateTime
    attribute :updated_at, Types::DateTime
  end
end

そこで User has one post みたいな関係が必要になりましたが、guideには別のEntityをschemaに記述する方法がありませんでした。そこでHanamiが内部的に使用している dry-types のドキュメントを見てみると Types.instance(Range) と記載があったのでこれを使用すればいけそうだなと感じ、以下のようなコードを試してみました。

class User < Hanami::Entity
  attributes do
    attribute :id, Types::String
    attribute :name, Types::String

    attribute :post, Types.Instance(Post)

    attribute :created_at, Types::DateTime
    attribute :updated_at, Types::DateTime
  end
end

いけそうかな、と思いましたがエラーが出ました。

他に使えそうなAPIもないので、hamami/modelソースコードを眺めていると https://github.com/hanami/model/blob/master/lib/hanami/model/types.rb にそれっぽいメソッド名のものが2つあったので試してみたところビンゴでした。

class User < Hanami::Entity
  attributes do
    attribute :id, Types::String
    attribute :name, Types::String

    attribute :post, Types::Entity(Post)
    attribute :posts, Types::Collection(Post)

    attribute :created_at, Types::DateTime
    attribute :updated_at, Types::DateTime
  end
end

最悪 initialize でチェックするかと思っていたので、スッキリした方法が見つかってよかったです。