建议搭配之前的 sequence diagram 一起服用!
在进到 Record Mapper 和 Factory 之前,先来介绍一下 dry-initializer,他替我们省略掉 constructor (在 ruby 中是 initialize
)中赋值给实例变数(instance variable)的工作,在 spec 中这样的特性让我们可以简单的替换掉跟外部依赖的 class。
require 'dry/initializer'
class User
extend Dry::Initializer
param :name, default: proc { nil }
option :age, default: proc { nil }
end
user = User.new 'Tom', age: 23
user.name # => 'Tom'
user.age # => 23
我们放在 initialize 的参数都是属於工具或模组化的 class,通常在 spec 中都会把这些 class 抽换掉,而 method 传入的才是那个 method 有用到的参数。
Record Mapper的职责是把 aggregate
的 hash
转成对应 db schema key 的 hash
,选择转成 hash
的原因是 hash
是 ruby 的 base type,如此一来便可以让 mapper 通用化到不同的外部资源(ORM、Database、其他 gem 等等)
class Order < Boxenn::Repositories::Mapper
def build(hash)
# key 是对应到 DB schema columns name,而 value 则是 entity 的 attibutes name
{
custom_serial_number: hash[:serial_number],
status: hash[:status],
created_at: hash[:puchased_at],
comment: hash[:comment],
}
end
end
Factory 的职责跟 Record Mapper 刚好恰恰相反,是把 source
转成 aggregate
,而在Boxenn::Repositories::Factory
中定义的介面也是 build,除此之外还需要使用 dry-initializer 指定 entity。
这边的 Factory 不是在 DDD 或 clean architecture 中的 factory,单纯只是一个转换器,名字是为了与 record mapper 作区别。
class Order < Boxenn::Repositories::Factory
# 指定 entity 让 factory 和 repository 使用
param :entity, default: -> { Entities::Order }
def build(source_object)
entity.new(
serial_number: source_object.custom_serial_number,
status: source_object.status,
puchased_at: source_object.created_at,
comment: source_object.comment,
)
end
end
下一篇会进一步扩充 record mapper,使每次在建立基础设施时更加快速。
>>: 自动化 End-End 测试 Nightwatch.js 之踩雷笔记:上传档案
大家好,我是来自台北教育大学玩游所的硕士生 May,在大学接触到如何写网页後,就毅然踏入了前端这个大...
当小菜渣也好一阵子了, 来记录一下 铁人赛结束後,也顺利的录取心目中满意的公司 十一月报到後就开始当...
取自 Artifact Austin: Leaving Pixels Behind - Todd ...
Laravel目录结构 先来说说各个目录及资料夹里面放置档案,并没有强制规定 根目录 app目录 a...
Laravel起步走 Laravel是一个MVC架构的PHP框架,分别是model(资料处理),co...