Skip to content
Persistence gem for Ruby objects using the Data Mapper pattern
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Perpetuity Build Status

Perpetuity is a simple Ruby object persistence layer that attempts to follow Martin Fowler's Data Mapper pattern, allowing you to use plain-old Ruby objects in your Ruby apps in order to decouple your domain logic from the database as well as speed up your tests. There is no need for your model classes to inherit from another class or even include a mix-in.

Your objects will hopefully eventually be able to be persisted into whichever database you like. Right now, only MongoDB is supported. Other persistence solutions will come later.

This gem was inspired by a blog post by Steve Klabnik.

How it works

In the Data Mapper pattern, the objects you work with don't understand how to persist themselves. This decouples them from the database and allows you to write your code without it in mind. We achieve this goal using Mappers.


Add the following to your Gemfile and run bundle to install it.

gem 'perpetuity', github: 'jgaskins/perpetuity'

Once it's got enough functionality to release, you'll be able to remove the git parameter.


The only currently supported persistence method is MongoDB. Other schemaless solutions can probably be implemented easily.

mongodb = host: '', db: 'example_db'
Perpetuity.configure do 
  data_source mongodb

Saving Objects

class Article
  attr_accessor :title, :body

class ArticleMapper < Perpetuity::Mapper
  attribute :title, String
  attribute :body, String

article =
article.title = 'New Article'
article.body = 'This is an article.'

ArticleMapper.insert article

Loading Objects

You can load all persisted objects of a particular class by invoking the all method on that class's mapper class. Example:


You can load specific objects by calling the find method with an ID param on that class's mapper class and passing in the criteria. You may also specify more general criteria using the select method with a block similar to Enumerable#select.

article = ArticleMapper.find params[:id]
users = { email == '' }
articles = { published_at < }
comments = { }

This will return a Perpetuity::Retrieval object, which will lazily retrieve the objects from the database. They will wait to hit the DB when you begin iterating over the objects so you can continue chaining methods.

articles = { published_at < }
articles = articles.sort(:published_at).reverse
articles = # built-in pagination

articles.each do |article| # This is when the DB gets hit
  # Display the pretty articles

Associations with Other Objects

If an object references another object (such as an article referencing its author), it must have a relationship identifier in its mapper class. For example:

class User

class Article
  attr_accessor :author

  def initialize(author) = author

class UserMapper < Perpetuity::Mapper

class ArticleMapper < Perpetuity::Mapper
  attribute :author, User

This allows you to write the following:

article = ArticleMapper.first
ArticleMapper.load_association! article, :author
user =

Customizing persistence

Setting the ID of a record to a custom value rather than using the DB default.

class ArticleMapper < Perpetuity::Mapper
  id { title.gsub(/\W+/, '-') } # use the article's parameterized title attribute as its ID


Right now, this code is pretty bare and there are possibly some design decisions that need some more refinement. You can help. If you have ideas to build on this, send some love in the form of pull requests or issues or tweets or e-mails and I'll do what I can for them.

Something went wrong with that request. Please try again.