ruby-on-rails – Ruby中的存储库或网关模式

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – Ruby中的存储库或网关模式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
如何在 Ruby中实现Repository或Gateway模式?

我来自一个C#世界,我通常抽象出我的数据访问,但是使用ActiveRecord作为Ruby中的默认数据访问机制,如何实现这一点并不明显.

我通常在C#中做的是使用抽象接口,然后为EFCustomerRepository,NHibernateCustomerRepository和InMemoryCustomerRepository提供具体的实现,并根据情况我注入匹配的具体实现.

那么现在,Ruby的方式是什么?!

据我所知,在动态语言中你不需要像DI(依赖注入)这样的东西.
Ruby具有强大的语言功能,可以实现mixins之类的功能.

但是你会定义mixin在类或模块级静态使用吗?

如果我想针对内存存储库进行开发,那么如何编写我的业务逻辑?在生产中我会切换到我的ActiveRecord-Repository?

如果我可能在错误的道路上,因为我习惯于用静态类型语言思考.如何以Ruby的方式处理这项任务?基本上我想让我的持久层抽象,它的实现可以互换.

编辑:我指的是robert c. martins (unclebob) keynote about architecture

谢谢你的帮助…

解决方法

我得到你说的话.我也来自.NET背景.摘要你的业务逻辑&持久性逻辑是一个好主意.我还没有找到适合你的宝石.但是你可以轻松地自己滚动一些东西.最后,存储库模式基本上是一个委托给持久层的类.

这是我做的:

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,以便将它们范围限定为当前用户或其他东西.

我正在努力找到正确的方法去做你所要求的事情,并且如果我找到的话就做一些关于它的文章.但就目前来说,已经足够在持久性和稳定性之间进行彻底切割.我的控制员.如果这样做得当,以后切换到不同的系统将不会是一个大麻烦.或者添加缓存等.

猜你在找的Ruby相关文章