ruby-on-rails - 在 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
我在这里错过了什么吗?如何以干净的方式验证我的事件?
解决方案
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_id
、data
和:
https://github.com/RailsEventStore/rails_event_store/blob/cfc91c9cb367e514ba1c6de1a711a7610780b520/ruby_event_store/lib/ruby_event_store/mappers/transformation/domain_event.rb#L9-L12。您还可以在那里看到从商店加载时它是如何实例化的。metadata
type
当您提供自己的映射器或仅替换RubyEventStore::Mappers::Transformation::DomainEvent
负责该转换时,可以更改此行为。
推荐阅读
- java - Android 无法使用 volley 发送 post 请求(BasicNetwork.performRequest: Unexpected response code 404)
- powershell - 不支持给定路径的格式(但在我看来还可以)
- python - 蟒蛇 | 熊猫如何将列内的列表拆分为多列
- heroku - 无法为 Heroku 应用程序使用自定义域
- sql - 如何修复动态 Sql 错误:-104;Token Unkown - 在 where 子句中使用子查询来过滤最大日期
- python - 将选定的文件复制到python中的目录
- java - JTable 不会在 fireTableChanged 上刷新
- javascript - 获取所有可用的列表
- ruby-on-rails - Rails - 仅在满足条件时发送关联表单
- python - Tkinter 窗口作为 App 类方法而不是新类或顶层(Python 3.X。)