首页 > 解决方案 > 在 RailsEventStore 中干净地验证事件模式

问题描述

我正在使用 Rails 和 RailsEventStore 构建 CQRS 和事件源应用程序。在 RailsEventStore 中,您似乎应该从 RailsEventStore::Event 继承表示事件的类。

class UserRegistered < RailsEventStore::Event
  …
end

这个基类公开了一个 event_id、一个数据散列和一个可选的元数据散列。据我了解,这看起来更像是 Greg Young 曾经称之为事件信封的东西,而我的域模型应该只关心存储在信封数据哈希中的实际事件。

现在我想对我的事件强制执行一个模式。但似乎 RailsEventStore 希望我为我的域模型区分的每种事件类型建模 RailsEventStore::Event 的子类(信封)。

在信封的子类中验证数据散列的内容感觉很麻烦和肮脏。我总是需要重写初始化方法并传递我真正不关心的东西。

class UserRegistered < RailsEventStore::Event
  def initialize(event_id: SecureRandom.uuid, metadata: nil, data: {})
    ensure_valid!(data)

    super(event_id: event_id, metadata: metadata, data: data)
  end

  def ensure_valid!(data)
    raise ArgumentError unless data[:user_id]
  end
end

通过访问所有事件属性event.data[:my_attribute]也感觉不好。为每个信封子类添加大量委托方法似乎也是一种浪费。

我宁愿为一个普通的 Ruby 对象建模,或者使用 Dry::Struct 之类的东西来对我的事件的内容属性强制执行模式。

class UserRegistered < Dry::Struct
  attribute :user_id, Dry::Types::String
end

我在这里错过了什么吗?如何以干净的方式验证我的事件?

标签: ruby-on-railsrubycqrsevent-sourcingrails-event-store

解决方案


Dry::Struct 模式的示例可以在示例应用程序存储库中找到:

https://github.com/RailsEventStore/cqrs-es-sample-with-res/blob/e4983433bc5d71252da58a23da9374f17e1d5cb3/ordering/lib/ordering/order_submitted.rb + https://github.com/RailsEventStore/cqrs-es-sample- with-res/blob/e4983433bc5d71252da58a23da9374f17e1d5cb3/ordering/lib/ordering/order_submitted.rb

虽然继承自是RailsEventStore::Event最简单的,但它不是必需的。Protobuf 集成就是一个很好的例子: https ://railseventstore.org/docs/protobuf/#defining-events 。它更像是一个事件信封。

传递给 RES的事件至少需要响应event_iddata和: https://github.com/RailsEventStore/rails_event_store/blob/cfc91c9cb367e514ba1c6de1a711a7610780b520/ruby_event_store/lib/ruby_event_store/mappers/transformation/domain_event.rb#L9-L12。您还可以在那里看到从商店加载时它是如何实例化的。metadatatype

当您提供自己的映射器或仅替换RubyEventStore::Mappers::Transformation::DomainEvent负责该转换时,可以更改此行为。

请比较: https ://github.com/RailsEventStore/rails_event_store/blob/cfc91c9cb367e514ba1c6de1a711a7610780b520/ruby_event_store/lib/ruby_event_store/mappers/default.rb

vs. https://github.com/RailsEventStore/rails_event_store/blob/cfc91c9cb367e514ba1c6de1a711a7610780b520/ruby_event_store/lib/ruby_event_store/mappers/protobuf.rb


推荐阅读