我来自一个C#世界,我通常抽象出我的数据访问,但是使用ActiveRecord作为Ruby中的默认数据访问机制,如何实现这一点并不明显.
我通常在C#中做的是使用抽象接口,然后为EFCustomerRepository,NHibernateCustomerRepository和InMemoryCustomerRepository提供具体的实现,并根据情况我注入匹配的具体实现.
那么现在,Ruby的方式是什么?!
据我所知,在动态语言中你不需要像DI(依赖注入)这样的东西.
Ruby具有强大的语言功能,可以实现mixins之类的功能.
但是你会定义mixin在类或模块级静态使用吗?
如果我想针对内存存储库进行开发,那么如何编写我的业务逻辑?在生产中我会切换到我的ActiveRecord-Repository?
如果我可能在错误的道路上,因为我习惯于用静态类型语言思考.如何以Ruby的方式处理这项任务?基本上我想让我的持久层抽象,它的实现可以互换.
编辑:我指的是robert c. martins (unclebob) keynote about architecture
谢谢你的帮助…
解决方法
这是我做的:
require 'active_support/core_ext/module/attribute_accessors' class GenericRepository def initialize(options = {}) @scope = options[:scope] @association_name = options[:association_name] end def self.set_model(model,options = {}) cattr_accessor :model self.model = model end def update(record,attributes) check_record_matches(record) record.update_attributes!(attributes) end def save(record) check_record_matches(record) record.save end def destroy(record) check_record_matches(record) record.destroy end def find_by_id(id) scoped_model.find(id) end def all scoped_model.all end def create(attributes) scoped_model.create!(attributes) end private def check_record_matches(record) raise(ArgumentError,"record model doesn't match the model of the repository") if not record.class == self.model end def scoped_model if @scope @scope.send(@association_name) else self.model end end end
然后你可以有一个Post存储库.
class PostRepository < GenericRepository set_model Post # override all because we also want to fetch the comments in 1 go. def all scoped_model.all(:include => :comments) end def count() scoped_model.count end end
只需在您的控制器中在before_filter或初始化或任何地方实例化它.在这种情况下,我将其范围限定为current_user,以便它仅获取这些记录并仅为当前用户自动创建帖子.
def initialize @post_repository = PostRepository.new(:scope => @current_user,:association_name => 'posts') end def index @posts = @post_repository.all respond_with @posts,:status => :ok end
我遇到了https://github.com/bkeepers/morphine这是一个很小的DI框架.它可能适合你:)但DI不是ruby中使用频繁的模式.此外,我实例化我的repos,以便将它们范围限定为当前用户或其他东西.
我正在努力找到正确的方法去做你所要求的事情,并且如果我找到的话就做一些关于它的文章.但就目前来说,已经足够在持久性和稳定性之间进行彻底切割.我的控制员.如果这样做得当,以后切换到不同的系统将不会是一个大麻烦.或者添加缓存等.