README.markdown in machinist-2.0.0.beta2 vs README.markdown in machinist-2.0

- old
+ new

@@ -1,26 +1,39 @@ # Machinist 2 *Fixtures aren't fun. Machinist is.* -- [Home page](http://github.com/notahat/machinist/tree/machinist2) -- [What's new in Machinist 2](http://wiki.github.com/notahat/machinist/machinist-2) -- [Installation](http://wiki.github.com/notahat/machinist/installation) -- [Documentation](http://wiki.github.com/notahat/machinist/getting-started) -- [Google group](http://groups.google.com/group/machinist-users) -- [Issue tracker](http://github.com/notahat/machinist/issues) +Machinist 2 is **still in beta**! +If you're using Rails 3, you'll want to give Machinist 2 a go, but be aware +that the documentation is still patchy. -# Introduction +That said, have a look at [the +specs](https://github.com/notahat/machinist/tree/master/spec), starting with +[the spec for +Machinable](https://github.com/notahat/machinist/blob/master/spec/machinable_spec.rb). +No, really, have a look. I wrote this code to be read, and the specs do a +pretty clean job of documenting what it all does. -Machinist makes it easy to create objects within your tests. It generates data +If, on the other hand, you want the tried, tested, and well-documented official +release version of Machinist, [then go with Machinist +1](http://github.com/notahat/machinist/tree/1.0-maintenance). + +- [Home page](http://github.com/notahat/machinist) +- [Google group](http://groups.google.com/group/machinist-users), for support +- [Bug tracker](http://github.com/notahat/machinist/issues), for reporting Machinist bugs + + +## Introduction + +Machinist makes it easy to create objects for use in tests. It generates data for the attributes you don't care about, and constructs any necessary -associated objects, leaving you to specify only the attributes you *do* care -about in your tests. For example: +associated objects, leaving you to specify only the fields you care about in +your test. For example: - describe Comment do - it "should not include spam in the without_spam scope" do + describe Comment, "without_spam scope" do + it "doesn't include spam" do # This will make a Comment, a Post, and a User (the author of the # Post), generate values for all their attributes, and save them: spam = Comment.make!(:spam => true) Comment.without_spam.should_not include(spam) @@ -32,28 +45,223 @@ require 'machinist/active_record' 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 Comment.blueprint do post - email { "commenter-#{sn}@example.com" } + email { "commenter#{sn}@example.com" } body { "Lorem ipsum..." } end -Check out the -[documentation](http://wiki.github.com/notahat/machinist/getting-started) for -more info. +## Installation +### Upgrading from Machinist 1 + +See [the wiki](http://wiki.github.com/notahat/machinist/machinist-2). + +### Rails 3 + +In your app's `Gemfile`, in the `group :test` section, add: + + gem 'machinist', '>= 2.0.0.beta2' + +Then run: + + bundle + rails generate 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` +inside the Application class: + + config.generators do |g| + g.fixture_replacement :machinist + end + +### Rails 2 + +See [the wiki](http://wiki.github.com/notahat/machinist/rails-2). + + +## Usage + +### Blueprints + +A blueprint describes how to generate an object. The blueprint takes care of +providing attributes that your test doesn't care about, leaving you to focus on +just the attributes that are important for the test. + +A simple blueprint might look like this: + + Post.blueprint do + title { "A Post" } + body { "Lorem ipsum..." } + end + +You can then construct a Post from this blueprint with: + + Post.make! + +When you call `make!`, Machinist calls `Post.new`, then runs through the +attributes in your blueprint, calling the block for each attribute to generate +a value. It then saves and reloads the Post. (It throws an exception if the +Post can't be saved.) + +You can override values defined in the blueprint by passing a hash to make: + + Post.make!(:title => "A Specific Title") + +If you want to generate an object without saving it to the database, replace +`make!` with `make`. + + +### Unique Attributes + +For attributes that need to be unique, you can call the `sn` method from +within the attribute block to get a unique serial number for the object. + + User.blueprint do + username { "user-#{sn}" } + end + + +### Associations + +If your object needs associated objects, you can generate them like this: + + Comment.blueprint do + post { Post.make } + end + +Calling `Comment.make!` will construct a Comment and its associated Post, and +save both. + +Machinist is smart enough to look at the association and work out what sort of +object it needs to create, so you can shorten the above blueprint to: + + Comment.blueprint do + post + end + +If you want to override the value for post when constructing the comment, you +can do this: + + post = Post.make(:title => "A particular title) + comment = Comment.make(:post => post) + + +For `has_many` and `has_and_belongs_to_many` associations, you can create +multiple associated objects like this: + + Post.blueprint do + comments(3) # Makes 3 comments. + end + + +### Named Blueprints + +Named blueprints let you define variations on an object. For example, suppose +some of your Users are administrators: + + User.blueprint do + name { "User #{sn}" } + email { "user-#{sn}@example.com" } + end + + User.blueprint(:admin) do + name { "Admin User #{sn}" } + admin { true } + end + +Calling: + + User.make!(:admin) + +will use the `:admin` blueprint. + +Named blueprints call the default blueprint to set any attributes not +specifically provided, so in this example the `email` attribute will still be +generated even for an admin user. + +You must define a default blueprint for any class that has a named blueprint, +even if the default blueprint is empty. + + +### Blueprints on Plain Old Ruby Objects + +Machinist also works with plain old Ruby objects. Let's say you have a class like: + + class Post + extend Machinist::Machinable + + attr_accessor :title + attr_accessor :body + end + +You can blueprint the Post class just like anything else: + + Post.blueprint do + title { "A title!" } + body { "A body!" } + end + +And `Post.make` will construct a new Post. + + +### Other Tricks + +You can refer to already assigned attributes when constructing a new attribute: + + Post.blueprint do + author { "Author #{sn}" } + body { "Post by #{object.author}" } + end + + +## Compatibility + +I've tested this with: + +Ruby versions: 1.8.7, 1.9.2 +Rails versions: 2.3, 3.0 + +It may well be happy with other versions too, but I'm not promising anything. +Compatibility patches are welcome. + + +## Developing + +The Machinist specs and source code were written to be read, and I'm pretty +happy with them. Don't be afraid to have a look under the hood! + +If you want to submit a patch: + +- Fork the project. +- Make your feature addition or bug fix. +- Add tests for it. This is important so I don't break it in a + future version unintentionally. +- Commit, do not mess with rakefile, version, or history. + (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull) +- Send me a pull request. Bonus points for topic branches. + + +## Status + +In active use in a number of large Rails 2 apps. + +Development has been sporadic, but is picking up again. + + ## Contributors Machinist is maintained by Pete Yandell ([pete@notahat.com](mailto:pete@notahat.com), [@notahat](http://twitter.com/notahat)) Other contributors include: @@ -65,21 +273,23 @@ [Perryn Fowler](http://github.com/perryn), [Niels Ganser](http://github.com/Nielsomat), [Jeremy Grant](http://github.com/jeremygrant), [Jon Guymon](http://github.com/gnarg), [James Healy](http://github.com/yob), +[Ben Hoskings](http://github.com/benhoskings), [Evan David Light](http://github.com/elight), [Chris Lloyd](http://github.com/chrislloyd), [Adam Meehan](http://github.com/adzap), [Kyle Neath](http://github.com/kneath), [Lawrence Pit](http://github.com/lawrencepit), +[Xavier Shay](http://github.com/xaviershay), [T.J. Sheehy](http://github.com/tjsheehy), [Roland Swingler](http://github.com/knaveofdiamonds), [Gareth Townsend](http://github.com/quamen), [Matt Wastrodowski](http://github.com/towski), [Ian White](http://github.com/ianwhite) Thanks to Thoughtbot's [Factory Girl](http://github.com/thoughtbot/factory_girl/tree/master). 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. - +