Skip to content
Browse files

Working my way through documenting everything.

  • Loading branch information...
1 parent 8c085e2 commit ba722419bfe16cbd35a6077a625906fa32220738 @notahat committed Jun 20, 2010
Showing with 96 additions and 76 deletions.
  1. +96 −76
@@ -2,120 +2,140 @@
*Fixtures aren't fun. Machinist is.*
-## What's New?
+And now, Machinist 2 gives you the convenience of Machinist, with the
+performance of fixtures.
-Now you get all the convenience of Machinist, with the performance of fixtures.
+See the wiki for [upgrade instructions and info on what's
+new]( in Machinist 2.
-When you create an object, Machinist 2 keeps the object around in the database.
-If, in a later test, you request an identical object, Machinist will give you
-the cached copy.
-## Introduction
+# Introduction
-Nobody loves fixtures. How do you avoid them?
+Machinist makes it easy to create test data within your tests. It generates
+data for the fields you don't care about, and constructs any necessary
+associated objects, leaving you to specify only the fields you *do* care about
+in your tests. For example:
-It would be nice to just make model objects as you need them, but your models
-probably have lots of required attributes, which means you end up writing
-something like:
+ describe Comment do
+ it "should not include spam in the without_spam scope" do
+ # This will make a Comment, a Post, and a User (the author of
+ # the Post), and generate values for all their attributes:
+ spam = Comment.make!(:spam => true)
- user = User.create!(:username => "fred", :email => "", :password => "secret", :password_confirmation => "secret")
-when your test only cares about one or two attributes.
-With Machinist, you just write:
- user = User.make!(:password => "secret")
-Machinist knows how to generate values for the attributes you don't specify in
-your test. How? You define a blueprint for User class in `spec/blueprints.rb`:
- User.bluerint do
- username { "user#{serial_number}" } # Each user gets a unique serial number.
- email { "#{attributes.username}" }
- password { "secret" }
- password_confirmation { attributes.password }
+ Comment.without_spam.should_not include(spam)
+ end
+You tell Machinist how to do this with blueprints:
-## Docs
-### Caching
+ require 'machinist/active_record'
-Whenever you generate an object using `make!`, Machinist keeps it in the
-database. If you request an identicaly object in another test, you'll get the
-cached object back.
+ User.blueprint do
+ username { "user#{sn}" } # Each user gets a unique serial number.
+ end
+ Post.blueprint do
+ author
+ title { "Post #{sn}" }
+ body { "Lorem ipsum..." }
+ end
-- Serial Numbers
-- Accessing Other Attributes
-- Associations
-- make vs make!
+ Comment.blueprint do
+ post
+ email { "commenter-#{sn}" }
+ body { "Lorem ipsum..." }
+ end
-## Example
+# Installation
-In `app/models/user.rb` you define your model:
+So far the generators only work with Rails 3 and RSpec. This will be fixed soon.
- class User < ActiveRecord::Base
- validates_presence_of :username, :email, :password
- validates_uniqueness_of :username
- validates_confirmation_of :password
- end
+## Rails 3
-In `spec/blueprints.rb` you define a blueprint for the user:
+Edit your app's `Gemfile` and, inside the `group :test` section, add:
- User.bluerint do
- username { "user#{sn}" }
- email { "#{attr.username}" }
- password { "secret" }
- password_confirmation { attr.password }
- end
+ gem 'machinist', '2.0.0.head', :git => 'git://', :branch => 'machinist2'
-In `spec/models/user_spec.rb` you use Machinist to make a user for you.
-Machinist uses the blueprint to generate any attributes you don't explicitly
+Then run:
- describe User do
- it "should match the user's password" do
- user = User.make!(:password => "special-password")
- user.password_matches?("special-password").should be_true
- user.password_matches?("wrong-password").should be_false
- end
- end
+ bundle install
+ rake machinist:install
+If you want Machinist to automatically add a blueprint to your blueprints file
+whenever you generate a model, add the following to your
+`config/application.rb` in the `config.generators` section:
-## What's New
+ g.fixture_replacement :machinist
-- Caching, FTW!!!!
-- Collections -- make lots of objects in one hit (experimental)
+# Documentation
-## What's Different
+Still to come!
-Machnist 2 is not a drop-in replacement for Machinist 1. Implementing
-caching has required substantial changes to the API.
+- Caching
+- Serial Numbers
+- Accessing Other Attributes
+- Associations
+- make vs make!
-- No more Sham
-- Use `make!` if you want a saved object, or `make` if you don't
-- Use `object` in the blueprint to access attributes that have already been
- assigned on the object being constructed
+# In The Works
-## What's Not There Yet
+## Not Done Yet
-- No easy upgrade path from Machinist 1
- No `make` method on associations
- No support for ORMs other than ActiveRecord
- Blueprints don't follow class inheritance
- No `plan` method
-## What's Broken
+## Currently Broken
- The master blueprint for a class has to be defined before any named
blueprints, or inheritance won't work
+## In The Planning Stage
-## Stuff I'm Still Thinking About
+- Support for constructing (and caching) complete graphs of objects in one hit
- Easy support for different construction strategies, e.g. generating all the
attributes and passing them to new as a hash
+# Community
+You can always find the [latest version on GitHub](
+If you have questions, check out the [Google Group](
+File bug reports and feature requests in the [issue tracker](
+## Contributors
+Machinist is maintained by Pete Yandell ([](, [@notahat](
+Other contributors include:
+[Marcos Arias](,
+[Jack Dempsey](,
+[Clinton Forbes](,
+[Perryn Fowler](,
+[Niels Ganser](,
+[Jeremy Grant](,
+[Jon Guymon](,
+[James Healy](,
+[Evan David Light](,
+[Chris Lloyd](,
+[Adam Meehan](,
+[Kyle Neath](,
+[Lawrence Pit](,
+[T.J. Sheehy](,
+[Roland Swingler](,
+[Gareth Townsend](,
+[Matt Wastrodowski](,
+[Ian White](
+Thanks to Thoughtbot's [Factory
+Girl]( Machinist was
+written because I loved the idea behind Factory Girl, but I thought the
+philosophy wasn't quite right, and I hated the syntax.

0 comments on commit ba72241

Please sign in to comment.
Something went wrong with that request. Please try again.