ser*_*nfo 8 ruby architecture design-patterns ruby-on-rails
如何在Ruby中实现Repository或Gateway模式?
我来自一个C#世界,我通常抽象出我的数据访问,但是使用ActiveRecord作为Ruby中的默认数据访问机制,如何实现这一点并不明显.
我通常会做在C#是抽象的接口工作,然后有具体的实现EFCustomerRepository
,NHibernateCustomerRepository
而且InMemoryCustomerRepository
并根据我注入相匹配的具体落实情况.
那么现在,Ruby的方式是什么?!
据我所知,在动态语言中你不需要像DI(依赖注入)这样的东西.Ruby具有强大的语言功能,可以实现mixins之类的功能.
但是你会定义mixin在类或模块级静态使用吗?
如果我想针对内存存储库开发并在生产中我将切换到我的ActiveRecord-Repository,如何编写我的业务逻辑?
如果我可能在错误的道路上,因为我习惯于用静态类型语言思考.如何以Ruby的方式处理这项任务?基本上我想让我的持久层抽象,它的实现可以互换.
编辑:我指的是罗伯特c.martins(unclebob)关于建筑的基调
谢谢你的帮助...
嗯,ActiveRecord 已经提供了抽象持久层 - 它有几个不同的适配器,允许它使用不同的数据库后端。此外,它是开源的,因此您可以自由地查看它是如何实现的。
乍一看,您可以看到它还有一个所有其他适配器都继承的AbstractAdapter,但是,由于 Ruby 是动态的鸭子类型语言,AbstractAdapter
不必包含将在子类中重写的抽象方法,也没有定义他们应该遵守的“契约”。
编辑:
下面是一个关于如何在 Ruby 中抽象存储的简单草图,但不确定它到底是什么模式:
# say you have an AR model of a person
class Person < ActiveRecord::Base
end
# and in-memory store of persons (simply, a hash)
IN_MEMORY_STORE = {
:Person => ['Tim', 'Tom', 'Tumb']
}
# this will abstract access
class MyAbstractModel
def initialize item, adapter
@item = item
@adapter = adapter
end
# get all elements from the store
def all
case @adapter
when :active_record
# pull from database:
Object.const_get(@item).all
when :in_memory_store
# get from in-memory store
IN_MEMORY_STORE[@item]
else
raise "Unknown adapter"
end
end
end
# get all Persons from in-memory storage...
p MyAbstractModel.new(:Person, :in_memory_store).all
# ...and from a database
p MyAbstractModel.new(:Person, :active_record).all
Run Code Online (Sandbox Code Playgroud)