将 source wrapper
、 record mapper
、 factory
都完成後,在 repository
里只需要简单的归位初始化後就完成了。
# 这边以 order 做举例,primary key 为 serial_number
class Order < Boxenn::Entity
def self.primary_keys
[:serial_number]
end
# 订单编号 (identity)
attribute :serial_number, Types::Coercible::String
# 状态
attribute :status, Types::Symbol.enum(successed: 0, refunded: 1, canceled: 2)
# 购买日期
attribute :puchased_at, Types::DateTime
# 备注
attribute :comment, Types::Coercible::String.optional.default(nil)
end
module Repositories
class Order < Boxenn::Repository
option :source_wrapper, default: -> { Wrapper::Order.new }
option :record_mapper, default: -> { Mapper::Order.new }
option :factory, default: -> { Factory::Order.new }
end
end
# 实际运用
repo = Repositories::Order.new
repo.find_by_identity(serial_number: 'ABC-1234567890') # 会回传 order 的 entity
repo.destroy(serial_number: 'ABC-1234567890') # 会删除资料库中的 record
order = Order.new(
serial_number: 'ABC-9876543210',
status: :successed,
puchased_at: Time.zone.now,
comment: '测试',
)
repo.save(order) # 会根据 serial_number = 'ABC-9876543210' 来找 record,如果有找到即更新资料,没有找到则建立一笔新 record
save
可以传入多个 entity 的 array ,一次更新或新增多笔资料
负责归纳复杂读取逻辑。
唯一定义的介面是 collect
,回传的资料会传入 factory 转成 entity,以ActiveRecord
为例回传为 array of models 即可。
下面范例一样以 ActiveRecord
为外部资源做示范:
require 'dry/initializer'
module Boxenn
module Repositories
class Query
extend Dry::Initializer
param :relation, default: proc { nil }
def collect
raise NotImplementedError
end
end
end
end
# Order Query
class OrderQuery < Boxenn::Repositories::Query
param :relation, default: -> { ::Models::Order }
def comment_include(key_word)
@relation = relation.where('comment LIKE ?', "%#{key_word}%")
self
end
def by_status(status)
@relation = relation.where(status: status)
self
end
def collect
relation
end
end
# 实际运用
repo = Repositories::Order.new
query = OrderQuery.new
query.comment_include('测试')
repo.find_by_query(query)
需要注意这边 query 有储存
Active::Record::Relation
, 因此不同的 method 之间可以 chain ,但如果想要新的搜寻结果就需要重新 new 一个 query
repo = Repositories::Order.new
query = OrderQuery.new
query.comment_include('测试').by_status(:refunded)
repo.find_by_query(query)
下篇会说明如何对整个 DAL 做测试。
<<: Day 15: 范式概述、结构化设计 (待改进中... )
前言 其实有一个特别的例子是just,直觉会认为just就是产生一个publisher等人来subs...
前言 我们终於要开使进入网页世界,一开始会觉得好多标签名称要记得、时不时也会忘记放入结束标签,而出现...
汇出自订 Provider 在介绍共享模组的时候,有提到可以透过 Module 的 exports ...
战略性和批判性思考是资安专业人员的基本技能。我认为,战略思考意味着从长期和高阶概念的角度进行思考。...
import matplotlib.pyplot as plt import requests im...