My team has run into the same problem in a large Rails app. We decided on a combination of service objects and data access objects (DAO) where appropriate. In a lot of cases this has really helped with the grep-ability of our codebase.
Service objects allow us to encapsulate complex operations that touch several domains and tables through a simple API. They're just plain objects.
DAOs fulfill a specific case of providing a simple CRUD API to a domain. We use a lot of DynamoDB so the DAO allows us to hide the complexity of reaching out to several tables in order to return a result. We also make sure that the DAO returns an immutable object that can't reach back into the datastore like an ActiveRecord object can (#save! methods come to mind).
The difference between a service object and a DAO is a little blurry but is enforced through quick design discussion and code reviews.
Service objects allow us to encapsulate complex operations that touch several domains and tables through a simple API. They're just plain objects.
DAOs fulfill a specific case of providing a simple CRUD API to a domain. We use a lot of DynamoDB so the DAO allows us to hide the complexity of reaching out to several tables in order to return a result. We also make sure that the DAO returns an immutable object that can't reach back into the datastore like an ActiveRecord object can (#save! methods come to mind).
The difference between a service object and a DAO is a little blurry but is enforced through quick design discussion and code reviews.