Ruby 中的存储库或网关模式
如何在 Ruby 中实现存储库或网关模式?
我来自 C# 世界,通常会抽象出我的数据访问,但使用 ActiveRecord 作为 Ruby 中的默认数据访问机制,如何实现这一点并不明显。
我通常在 C# 中做的是使用抽象接口,然后根据具体情况对 EFCustomerRepository、NHibernateCustomerRepository 和 InMemoryCustomerRepository 进行具体实现我注入匹配的具体实现。
那么现在,Ruby 的方式是什么?!
据我了解,在动态语言中,你不需要像 DI(依赖注入)这样的东西。 Ruby 具有强大的语言功能,可以实现 mixin 之类的功能。
但是您会定义 mixin 在类或模块级别静态使用吗?
如果我想针对内存存储库进行开发并在生产中切换到 ActiveRecord-Repository,我该如何编写业务逻辑?
如果这里可能走错了路,因为我习惯用静态类型语言思考。有人会如何用 Ruby 方式解决这个任务?基本上我想让我的持久层变得抽象,并且它的实现可以互换。
编辑:我指的是罗伯特c.马丁斯(unclebob)关于架构的主题演讲
感谢您的帮助...
How can I implement the Repository or Gateway pattern in Ruby?
I come from a C# world and I usually abstract away my data access but with ActiveRecord as the default data access mechanism in Ruby, it's not obvious how to accomplish that.
What I usually would do in C# is work with abstract interfaces and then have a concrete implementation for EFCustomerRepository
, NHibernateCustomerRepository
and InMemoryCustomerRepository
and depending on the situation I inject the matching concrete implementation.
So now, what’s the Ruby way?!
As far as I understand it, in dynamic languages you would not need something like DI (dependency injection).
And Ruby has powerful language features to allow things like mixins.
But you would define the mixin to use statically on class or module-level?
How do I write my business logic if I want to develop against an in-memory repository and in production I would switch to my ActiveRecord-Repository?
If might be on the wrong path here since I'm used to thinking in a statically typed language. How would someone tackle this task the Ruby way? Basically I want to make my persistence layer abstract and it's implementations interchangeable.
EDIT: I am referring to robert c. martins (unclebob) keynote about architecture
Thanks for any help...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我明白你在说什么。我也有 .NET 背景。抽象出您的业务逻辑和逻辑在我看来,持久性逻辑是个好主意。我还没有找到适合你的宝石。但您可以轻松地自己制作一些简单的东西。最后,存储库模式基本上是一个委托给持久层的类。
这就是我所做的:
然后你可以拥有一个 Post 存储库。
只需在控制器中的 before_filter 或初始化或任何地方实例化它即可。在本例中,我将其范围限定为 current_user,以便它仅获取这些记录并仅为当前用户自动创建帖子。
我遇到了 https://github.com/bkeepers/morphine 这是一个小型 DI 框架。它可能对你有用:)但是 DI 并不是 ruby 中广泛使用的模式。此外,我还实例化了我的存储库,以便将它们的范围限定为当前用户或其他用户。
我正在寻求找到正确的方法来完成您所要求的事情,如果我找到了,我会写一些关于它的文章。但就目前而言,它已经足以在持久性和持久性之间做出明确的划分。我的控制器。如果做得正确,以后切换到不同的系统不会有太大麻烦。或者添加缓存等。
I get what you are saying. I come from a .NET background as well. Abstracting away your business logic & persistance logic is imo a good idea. I haven't found a gem that does it for you yet. But you can easily roll something simple yourself. In the end a repository pattern is basically a class that delegates to your persistance layer.
Here is what I do:
And then you could for example have a Post repository.
Just instantiate it in your controller in a before_filter or initialize or wherever. In this case I'm scoping it to the current_user so that it only fetches those records and automatically create posts only for the current user.
I came across https://github.com/bkeepers/morphine which is a tiny DI framework. It could work for you :) But DI isn't a heavily used pattern in ruby. Also, I instantiate my repos in order to scope them to a current user or something else.
I'm on a quest to find the right way to do just what you ask and do a little write-up about it if I ever do find it. But for now it's already sufficient to make the clean cut between persistance & my controllers. If this is done properly it won't be a big hassle to switch to a different system later on. Or add caching etc.
好吧,ActiveRecord 已经提供了抽象持久层 - 它有 几个不同的适配器 允许它使用不同的适配器数据库后端。此外,它是开源的,因此您可以自由地查看它是如何实现的。
乍一看,您会发现它还有一个 AbstractAdapter 所有其他适配器然而,由于 Ruby 是动态的鸭子类型语言,AbstractAdapter 不必包含将在子类中重写的抽象方法,也不必定义他们应该遵守的“契约”。
编辑:
这是一个关于如何在 Ruby 中抽象存储的简单草图,不确定它到底是什么模式:
Well, ActiveRecord already provides abstract persistence layer - it has several different adapters allowing it to use different database backends. Also, it's open-source so you are free to take a look at how it has been achieved.
Upon the first glance you can see that it also has an AbstractAdapter that all other adapters inherit, however, as Ruby is dynamic, duck-typing language,
AbstractAdapter
doesn't have to contain abstract methods which will be overridden in children classes, neither defines a "contract" that they should honour.Edit:
Here's a simple sketch on how you could abstract away your storage in Ruby, not sure which pattern exactly it is:
@serverinfo,我对 C# 不太了解。但当我从 Java/C 背景转向 Ruby 时,当我意识到这种语言到底有多么灵活时,我感到震惊。你说你真正的问题是“抽象出你的持久层并使其可交换”。您还问“我将如何编写业务逻辑”。
我建议您抛弃先入之见,问问自己:“我希望如何在我的业务逻辑层中表达数据访问/存储”?不要担心你认为能做什么或不能做什么;如果您能弄清楚您希望界面如何工作,那么可能有一种方法可以在 Ruby 中完成。
您还必须决定如何指定要使用的具体实现。您是否可能希望对不同的模型对象使用不同的数据存储?您可能想在运行时切换吗?您想在配置文件或代码中指定要使用的后端吗?如果您可以决定想要做什么,Stack Overflow 上有很多人可以帮助您弄清楚如何去做。
@serverinfo, I don't know much about C#. But when I came to Ruby from a Java/C background, I was blown away when I realized how flexible this language really is. You say that your real problem here is to "abstract away your persistence layer and make it exchangeable". You also asked "how will I write the business logic".
I suggest that you throw away your preconceptions and ask yourself: "how would I like to express data access/storage within my business logic layer"? Don't worry about what you think can or can't be done; if you can figure out how you would like the interface to work, there is probably a way it can be done in Ruby.
You will also have to decide how you want to specify the concrete implementation to be used. Is it possible you will want to use a different data store for different model objects? Might you want to switch at run-time? Would you like to specify the backend to be used in a configuration file, or in code? If you can decide what you want to do, there are lots of people on Stack Overflow who can help you figure out how to do it.