Я понимаю, что вы говорите. Я также пришел из .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. Кроме того, я создаю экземпляры своих репозиториев, чтобы охватить их текущим пользователем или чем-то еще.
Я нахожусь в поиске правильного способа сделать то, что вы просите, и написать немного об этом, если я когда-нибудь найду это. Но на данный момент уже достаточно провести чистый разрыв между стойкостью и моими контроллерами. Если это сделано правильно, то переключение на другую систему в дальнейшем не составит большого труда. Или добавить кеширование и т. Д.