A model factory - say no to fixtures.
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Letterpress Build Status

Letterpress is a lightweight model generator that replaces fixture files.


Add this line to your application's Gemfile:

gem 'letterpress'

And then execute:

$ bundle

Or install it yourself as:

$ gem install letterpress


Rails, ActiveRecord and minitest

  1. Update Gemfile

    group :development, :test do
      gem 'letterpress', :require => 'letterpress/rails'
  2. Install the gem

     $ bundle install
  3. Update config/application.rb

    config.generators do |g|
      g.test_framework :mini_test, :spec => true, :fixture_replacement => :letterpress
  4. Generate (test|spec)/blueprint.rb file

     $ rails generate letterpress:install
  5. Generate a model object with its factory

     $ rails generate model Comment post_id:integer body:text
  6. It adds to the end of file (test|spec)/blueprint.rb

    class Comment < Blueprint(ProxyMethods)
      default do
        post_id { 1 }
        body { "MyText" }
  7. Modify the generated blueprint according to your preferences

    class Comment < Blueprint(ProxyMethods)
      default do
        post { Post.make.new }
        body { "MyText" }
  8. Write tests in test/comment_test.rb

    require "minitest_helper"
    class CommentTest < MiniTest::Rails::Model
      before do
        @comment = Comment.make.new
      it "must be valid" do
        @comment.valid?.must_equal true


Don't put the blueprint file in the support directory, if you do, the blueprint file will be required to early. It should be placed directly in the spec folder: spec/blueprint.rb If you do as describe below, the blueprint file is placed in the right place.

  1. Update config/application.rb
config.generators do |g|
  g.test_framework :rspec, :fixture_replacement => :letterpress
  1. Generate spec/blueprint.rb file
rails generate letterpress:install

Blueprint Class

A blueprint for a model is defined inside the Letterpress module; the class name of the blueprint must be the same as the models class name.

Below is an example of a Letterpress User class. Letterpress has two methods for defining blueprints: default and define; default can be used once in each class but define can be used as many time as you like. In this example the admin attribute is overridden by the admin block. The admin block will inherit the other attributes defined inside the default block.

module Letterpress
  class User < Blueprint(ProxyMethods)
    default do
      email { "user@example.com" }
      admin { false }

    define(:admin) do
      admin { true }

user = User.make # => returns a proxy object (an instance of Letterpress::User)
user.admin # => false; itdelegates to an instance of the User class
user.email # => "user@example.com"

user = User.make(:admin)
user.admin # => true
user.email # => "user@example.com"

user = User.make(:admin, admin: false)
user.admin # => false
user.email # => "user@example.com"

Unique Attributes

For attributes that must be unique, you can call the sn method within the attribute block to get a unique serial number for the object.

email { "user-#{sn}@example.com" } # Each email gets a unique serial number.

user1 = User.make
user2 = User.make

user1.email # => "user1@example.com"
user2.email # => "user2@example.com"


When you create associations you don't have to persist them inside the blueprint.

  • has_many
# When defining a has_many association, you define it with an array.
# These 2 comments will only be persisted in the database when Post.make.save 
# is called, and not when Post.make or Post.make.new is called. 
comments { [ Comment.make.new, Comment.make.new ] }
  • belongs_to
# Post.make.new defines a non persisted post instance.
# The post instance will only be saved to the database if
# Comment.make.save is called.
post { Post.make.new }

What you must know to create a blueprint class:

  • The class methods default and define is used for defining default attribute values.
  • An attribute values must be defined inside a block: {}.
  • The sn method is used inside an attribute block to create unique attribute values, e.g if each user instance must have a unique email address.

Creating Object

Letterpress ads make to each ActiveRecord class; When make is called on an ActiveRecord class, it returns a proxy object that will delegate its received messages to the ActiveRecord instance.

The proxy object implements these methods:

  • new - returns the object under test or raises an exception if the object isn't valid.
  • new! - returns the object under test, even if not valid.
  • save - returns the persisted object under test or raises an exception if the object isn't valid.
User.make # Returns instance of Letterpress::User
User.make(:admin) # Returns instance of Letterpress::User
User.make(:admin, email: "foo@bar.com") # Returns instance of Letterpress::User

User.make.new # Returns a new User instance
User.make(:admin).save # Returns a persisted User instance
User.make(:admin, email: "foo@bar.com").new! # Returns a new User instance

Creating global ProxyMethods

Since each Letterpress class inherits from ProxyMethods, we can define methods in that module and they will be added to each proxy object.

In the code snippet below I have added a save_and_relod method that will be available on every proxy object.

module Letterpress
  module ProxyMethods
    def save_and_reload
      record = save
      @object = @object.class.find(record.id)

user = User.make.save_and_reload

Creating ProxyMethods on a class

If you want to add a method to only one proxy object, see code below.

module Letterpress
  class User < Blueprint(ProxyMethods)
    default do

    def password(password)
      @object.password = "#{password} - in proxy" 

user = User.make.password("secret").save
user.password # => "secret - in proxy"

Overriding .make

If you for some reason want to do something with the proxy object before returning it, you can do that, see code below.

module Letterpress
  class User < Blueprint(ProxyMethods)
    default do

    def self.make
     user = super
     # do something with the proxy object before returning it
     user.password =  "I always have this value"

user = User.make.new
user.password # => "I always have this value"


Ruby version 1.9.2 and 1.9.3 and Rails version 3.1

GemTesters has more information on which platforms Letterpress is tested.


gem install rubygems-test
gem test letterpress

For more info see: GemTesters



  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request