machinist_redux 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +17 -0
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.rubocop.yml +60 -0
- data/.rubocop_todo.yml +92 -0
- data/.travis.yml +23 -0
- data/Appraisals +11 -0
- data/Gemfile +32 -0
- data/LICENSE.txt +21 -0
- data/README.md +307 -0
- data/Rakefile +20 -0
- data/gemfiles/rails_4.2.gemfile +38 -0
- data/gemfiles/rails_4.2.gemfile.lock +232 -0
- data/gemfiles/rails_5.0.gemfile +38 -0
- data/gemfiles/rails_5.0.gemfile.lock +232 -0
- data/gemfiles/rails_5.1.gemfile +34 -0
- data/gemfiles/rails_5.1.gemfile.lock +231 -0
- data/lib/generators/machinist/install/USAGE +2 -0
- data/lib/generators/machinist/install/install_generator.rb +46 -0
- data/lib/generators/machinist/install/templates/blueprints.rb +9 -0
- data/lib/generators/machinist/install/templates/machinist.rb.erb +7 -0
- data/lib/generators/machinist/model/model_generator.rb +11 -0
- data/lib/machinist.rb +5 -0
- data/lib/machinist/active_record.rb +14 -0
- data/lib/machinist/active_record/blueprint.rb +14 -0
- data/lib/machinist/active_record/lathe.rb +21 -0
- data/lib/machinist/blueprint.rb +84 -0
- data/lib/machinist/exceptions.rb +30 -0
- data/lib/machinist/lathe.rb +65 -0
- data/lib/machinist/machinable.rb +100 -0
- data/lib/machinist/version.rb +3 -0
- data/machinist.gemspec +23 -0
- data/spec/machinist/active_record_spec.rb +106 -0
- data/spec/machinist/blueprint_inheritance_spec.rb +101 -0
- data/spec/machinist/blueprint_spec.rb +76 -0
- data/spec/machinist/exceptions_spec.rb +16 -0
- data/spec/machinist/machinable_spec.rb +91 -0
- data/spec/spec_helper.rb +110 -0
- data/spec/support/active_record_environment.rb +62 -0
- metadata +94 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a6975277474c2f278dd63f6ebaf01e930e4e830b
|
4
|
+
data.tar.gz: 0f4f61f505cb8aa1dedc0abc7d55984d07fee225
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6c1d8c9400d7ac81391d511c57dd655ac5d8f9c511e4a075c58178935c8360cd51af43a3610283cc742c93f27a0ab3a334685f0f9f0b00a43d464141d880dc66
|
7
|
+
data.tar.gz: 7efa8ffa828f5721186c24f1036d78b1523fa9a91a77d36ae763fad5995278c5516bbc3dedf0fe81561ddd27f03f8502bce7e4f0d27821c4f22691514351534b
|
data/.codeclimate.yml
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.DS_Store
|
6
|
+
.rbenv-*
|
7
|
+
.rbx
|
8
|
+
.rbxpkg
|
9
|
+
.ruby-gemset
|
10
|
+
.ruby-version
|
11
|
+
.rvmrc
|
12
|
+
.yardoc
|
13
|
+
_yardoc
|
14
|
+
coverage
|
15
|
+
doc/
|
16
|
+
Gemfile.lock
|
17
|
+
InstalledFiles
|
18
|
+
lib/bundler/man
|
19
|
+
rdoc
|
20
|
+
spec/reports
|
21
|
+
tags
|
22
|
+
test/tmp
|
23
|
+
test/version_tmp
|
24
|
+
tmp
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
---
|
2
|
+
require: rubocop-rspec
|
3
|
+
inherit_from: .rubocop_todo.yml
|
4
|
+
|
5
|
+
AllCops:
|
6
|
+
TargetRubyVersion: 2.2
|
7
|
+
DisplayCopNames: true
|
8
|
+
Exclude:
|
9
|
+
- 'tmp/**/*'
|
10
|
+
|
11
|
+
Style/MixinGrouping:
|
12
|
+
Exclude:
|
13
|
+
- 'spec/**/*.rb'
|
14
|
+
|
15
|
+
Metrics/BlockLength:
|
16
|
+
CountComments: false # count full line comments?
|
17
|
+
Exclude:
|
18
|
+
- '**/*_spec.rb'
|
19
|
+
|
20
|
+
StringLiterals:
|
21
|
+
EnforcedStyle: single_quotes
|
22
|
+
Enabled: true
|
23
|
+
|
24
|
+
DotPosition:
|
25
|
+
EnforcedStyle: leading
|
26
|
+
Enabled: true
|
27
|
+
|
28
|
+
ClassAndModuleChildren:
|
29
|
+
EnforcedStyle: nested
|
30
|
+
Enabled: true
|
31
|
+
|
32
|
+
Documentation:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
FileName:
|
36
|
+
Enabled: true
|
37
|
+
|
38
|
+
LineLength:
|
39
|
+
Max: 120
|
40
|
+
Enabled: true
|
41
|
+
|
42
|
+
Style/ExtraSpacing:
|
43
|
+
Enabled: true
|
44
|
+
|
45
|
+
Lint/LiteralInInterpolation:
|
46
|
+
AutoCorrect: true
|
47
|
+
|
48
|
+
Style/ModuleFunction:
|
49
|
+
EnforcedStyle: extend_self # Allows us to have private methods too
|
50
|
+
|
51
|
+
Style/PercentLiteralDelimiters:
|
52
|
+
# Hound and CodeClimate are currently using an old version of Rubocop with
|
53
|
+
# different defaults, so we set them explicitly here.
|
54
|
+
PreferredDelimiters:
|
55
|
+
default: ()
|
56
|
+
'%i': '[]'
|
57
|
+
'%I': '[]'
|
58
|
+
'%r': '{}'
|
59
|
+
'%w': '[]'
|
60
|
+
'%W': '[]'
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2017-05-16 15:42:20 +0100 using RuboCop version 0.48.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
Metrics/AbcSize:
|
11
|
+
Max: 17
|
12
|
+
|
13
|
+
# Offense count: 1
|
14
|
+
Metrics/CyclomaticComplexity:
|
15
|
+
Max: 7
|
16
|
+
|
17
|
+
# Offense count: 1
|
18
|
+
# Configuration parameters: CountComments.
|
19
|
+
Metrics/MethodLength:
|
20
|
+
Max: 13
|
21
|
+
|
22
|
+
# Offense count: 1
|
23
|
+
Metrics/PerceivedComplexity:
|
24
|
+
Max: 8
|
25
|
+
|
26
|
+
# Offense count: 1
|
27
|
+
RSpec/DescribeMethod:
|
28
|
+
Exclude:
|
29
|
+
- 'spec/machinist/exceptions_spec.rb'
|
30
|
+
|
31
|
+
# Offense count: 17
|
32
|
+
# Configuration parameters: Max.
|
33
|
+
RSpec/ExampleLength:
|
34
|
+
Exclude:
|
35
|
+
- 'spec/machinist/active_record_spec.rb'
|
36
|
+
- 'spec/machinist/blueprint_inheritance_spec.rb'
|
37
|
+
- 'spec/machinist/blueprint_spec.rb'
|
38
|
+
- 'spec/machinist/machinable_spec.rb'
|
39
|
+
|
40
|
+
# Offense count: 2
|
41
|
+
RSpec/IteratedExpectation:
|
42
|
+
Exclude:
|
43
|
+
- 'spec/machinist/blueprint_spec.rb'
|
44
|
+
- 'spec/machinist/machinable_spec.rb'
|
45
|
+
|
46
|
+
# Offense count: 21
|
47
|
+
RSpec/MultipleExpectations:
|
48
|
+
Max: 6
|
49
|
+
|
50
|
+
# Offense count: 2
|
51
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
52
|
+
# SupportedStyles: nested, compact
|
53
|
+
Style/ClassAndModuleChildren:
|
54
|
+
Exclude:
|
55
|
+
- 'lib/machinist/active_record/blueprint.rb'
|
56
|
+
- 'lib/machinist/active_record/lathe.rb'
|
57
|
+
|
58
|
+
# Offense count: 1
|
59
|
+
# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
|
60
|
+
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
|
61
|
+
Style/FileName:
|
62
|
+
Exclude:
|
63
|
+
- 'Appraisals'
|
64
|
+
|
65
|
+
# Offense count: 1
|
66
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
67
|
+
# SupportedStyles: format, sprintf, percent
|
68
|
+
Style/FormatString:
|
69
|
+
Exclude:
|
70
|
+
- 'lib/machinist/blueprint.rb'
|
71
|
+
|
72
|
+
# Offense count: 3
|
73
|
+
# Configuration parameters: MinBodyLength.
|
74
|
+
Style/GuardClause:
|
75
|
+
Exclude:
|
76
|
+
- 'lib/generators/machinist/install/install_generator.rb'
|
77
|
+
- 'lib/machinist/lathe.rb'
|
78
|
+
|
79
|
+
# Offense count: 1
|
80
|
+
Style/MethodMissing:
|
81
|
+
Exclude:
|
82
|
+
- 'lib/machinist/lathe.rb'
|
83
|
+
|
84
|
+
# Offense count: 1
|
85
|
+
# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist.
|
86
|
+
# NamePrefix: is_, has_, have_
|
87
|
+
# NamePrefixBlacklist: is_, has_, have_
|
88
|
+
# NameWhitelist: is_a?
|
89
|
+
Style/PredicateName:
|
90
|
+
Exclude:
|
91
|
+
- 'spec/**/*'
|
92
|
+
- 'lib/machinist/blueprint.rb'
|
data/.travis.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
---
|
2
|
+
language: ruby
|
3
|
+
|
4
|
+
rvm:
|
5
|
+
- ruby-head
|
6
|
+
- 2.4.1
|
7
|
+
- 2.3.4
|
8
|
+
- 2.2.6
|
9
|
+
|
10
|
+
gemfile:
|
11
|
+
- gemfiles/rails_4.2.gemfile
|
12
|
+
- gemfiles/rails_5.0.gemfile
|
13
|
+
- gemfiles/rails_5.1.gemfile
|
14
|
+
|
15
|
+
matrix:
|
16
|
+
allow_failures:
|
17
|
+
- rvm: ruby-head
|
18
|
+
|
19
|
+
before_install:
|
20
|
+
- gem update bundler
|
21
|
+
|
22
|
+
after_success:
|
23
|
+
- bundle exec codeclimate-test-reporter
|
data/Appraisals
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
appraise 'rails-4.2' do
|
2
|
+
gem 'activerecord', '~> 4.2.8', group: :test, require: false
|
3
|
+
end
|
4
|
+
|
5
|
+
appraise 'rails-5.0' do
|
6
|
+
gem 'activerecord', '~> 5.0.3', group: :test, require: false
|
7
|
+
end
|
8
|
+
|
9
|
+
appraise 'rails-5.1' do
|
10
|
+
gem 'activerecord', '~> 5.1.1', group: :test, require: false
|
11
|
+
end
|
data/Gemfile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
gemspec
|
3
|
+
ruby RUBY_VERSION
|
4
|
+
|
5
|
+
group :development do
|
6
|
+
gem 'appraisal', require: false
|
7
|
+
gem 'gem-release', require: false
|
8
|
+
gem 'github_changelog_generator', require: false
|
9
|
+
gem 'guard', require: false
|
10
|
+
gem 'guard-rspec', require: false
|
11
|
+
gem 'guard-rubocop', require: false
|
12
|
+
gem 'guard-rubycritic', require: false
|
13
|
+
gem 'rdoc', require: false
|
14
|
+
gem 'rubocop-rspec', require: false
|
15
|
+
end
|
16
|
+
|
17
|
+
group :test do
|
18
|
+
gem 'codeclimate-test-reporter', require: false
|
19
|
+
gem 'coveralls', require: false
|
20
|
+
gem 'fuubar', require: false
|
21
|
+
gem 'rspec', require: false
|
22
|
+
gem 'rspec_junit_formatter', require: false
|
23
|
+
gem 'simplecov', '~> 0.14', require: false
|
24
|
+
end
|
25
|
+
|
26
|
+
platforms :ruby do
|
27
|
+
gem 'sqlite3'
|
28
|
+
end
|
29
|
+
|
30
|
+
platforms :jruby do
|
31
|
+
gem 'activerecord-jdbcsqlite3-adapter'
|
32
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2008-2017 Pete Yandell, Attila Györffy, Dominic Sayers
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,307 @@
|
|
1
|
+
# Machinist 3
|
2
|
+
|
3
|
+
*Fixtures aren't fun. Machinist was.*
|
4
|
+
|
5
|
+
[![Gem version](https://badge.fury.io/rb/machinist_redux.svg)](https://rubygems.org/gems/machinist_redux)
|
6
|
+
[![Gem downloads](https://img.shields.io/gem/dt/machinist_redux.svg)](https://rubygems.org/gems/machinist_redux)
|
7
|
+
[![Build Status](https://travis-ci.org/dominicsayers/machinist.svg?branch=master)](https://travis-ci.org/dominicsayers/machinist)
|
8
|
+
[![Code Climate](https://codeclimate.com/github/dominicsayers/machinist/badges/gpa.svg)](https://codeclimate.com/github/dominicsayers/machinist)
|
9
|
+
[![Test Coverage](https://codeclimate.com/github/dominicsayers/machinist/badges/coverage.svg)](https://codeclimate.com/github/dominicsayers/machinist/coverage)
|
10
|
+
[![Dependency Status](https://gemnasium.com/badges/github.com/dominicsayers/machinist.svg)](https://gemnasium.com/github.com/dominicsayers/machinist)
|
11
|
+
[![Security](https://hakiri.io/github/dominicsayers/machinist/master.svg)](https://hakiri.io/github/dominicsayers/machinist/master)
|
12
|
+
|
13
|
+
- [Home page](https://github.com/dominicsayers/machinist)
|
14
|
+
- [Google group](https://groups.google.com/group/machinist-users), for support
|
15
|
+
- [Bug tracker](https://github.com/dominicsayers/machinist/issues), for reporting Machinist bugs
|
16
|
+
|
17
|
+
If you want Machinist 1, [go here](https://github.com/notahat/machinist/tree/1.0-maintenance).
|
18
|
+
|
19
|
+
If you want support for Rails 3 or Rubies prior to 2.2, [go here](https://github.com/attilagyorffy/machinist).
|
20
|
+
|
21
|
+
## Status
|
22
|
+
|
23
|
+
This is a fork of [Pete Yandell's Machinist](http://github.com/notahat/machinist). The original gem was abandoned for the reasons given below, as are most of its forks. The purpose of this fork is to keep Machinist under maintenance for legacy projects that have upgraded to Ruby 2.2 or later and Rails 4.2 or later, but still have Machinist factories in the test environment.
|
24
|
+
|
25
|
+
I'm pleased to say that Pete's code runs fine under Ruby 2.2, 2.3 & 2.4 and Rails 4.2, 5.0 and 5.1. I have allowed [RuboCop](https://github.com/bbatsov/rubocop) and [RuboCop RSpec](https://github.com/backus/rubocop-rspec) to suggest some changes, and I have converted to the more up-to-date RSpec syntax using [Transpec](https://github.com/yujinakayama/transpec). Few if any manual changes were needed.
|
26
|
+
|
27
|
+
Pete Yandell's reason for abandoning Machinist is that he found himself with less and less need for factories in tests. He recommends Bo Jeanes' [excellent article on the topic](http://bjeanes.com/2012/02/factories-breed-complexity).
|
28
|
+
|
29
|
+
## Introduction
|
30
|
+
|
31
|
+
Machinist makes it easy to create objects for use in tests. It generates data
|
32
|
+
for the attributes you don't care about, and constructs any necessary
|
33
|
+
associated objects, leaving you to specify only the fields you care about in
|
34
|
+
your test. For example:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
describe Comment, 'without_spam scope' do
|
38
|
+
it "doesn't include spam" do
|
39
|
+
# This will make a Comment, a Post, and a User (the author of the
|
40
|
+
# Post), generate values for all their attributes, and save them:
|
41
|
+
spam = Comment.make!(spam: true)
|
42
|
+
|
43
|
+
Comment.without_spam.should_not include(spam)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
You tell Machinist how to do this with blueprints:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
require 'machinist/active_record'
|
52
|
+
|
53
|
+
User.blueprint do
|
54
|
+
username { "user#{sn}" } # Each user gets a unique serial number.
|
55
|
+
end
|
56
|
+
|
57
|
+
Post.blueprint do
|
58
|
+
author
|
59
|
+
title { "Post #{sn}" }
|
60
|
+
body { 'Lorem ipsum...' }
|
61
|
+
end
|
62
|
+
|
63
|
+
Comment.blueprint do
|
64
|
+
post
|
65
|
+
email { "commenter#{sn}@example.com" }
|
66
|
+
body { 'Lorem ipsum...' }
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
## Installation
|
71
|
+
|
72
|
+
### Upgrading from Machinist 1
|
73
|
+
|
74
|
+
See [the wiki](http://wiki.github.com/notahat/machinist/machinist-2).
|
75
|
+
|
76
|
+
### Rails 4 and 5
|
77
|
+
|
78
|
+
In your app's `Gemfile`, in the `group :test` section, add:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
gem 'machinist_redux'
|
82
|
+
```
|
83
|
+
|
84
|
+
Then run:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
bundle install
|
88
|
+
rails generate machinist:install
|
89
|
+
```
|
90
|
+
|
91
|
+
If you want Machinist to automatically add a blueprint to your blueprints file
|
92
|
+
whenever you generate a model, add the following to your `config/application.rb` inside the Application class:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
config.generators do |g|
|
96
|
+
g.fixture_replacement :machinist
|
97
|
+
end
|
98
|
+
```
|
99
|
+
|
100
|
+
## Usage
|
101
|
+
|
102
|
+
### Blueprints
|
103
|
+
|
104
|
+
A blueprint describes how to generate an object. The blueprint takes care of
|
105
|
+
providing attributes that your test doesn't care about, leaving you to focus on
|
106
|
+
just the attributes that are important for the test.
|
107
|
+
|
108
|
+
A simple blueprint might look like this:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
Post.blueprint do
|
112
|
+
title { 'A Post' }
|
113
|
+
body { 'Lorem ipsum...' }
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
You can then construct a Post from this blueprint with:
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
Post.make!
|
121
|
+
```
|
122
|
+
|
123
|
+
When you call `make!`, Machinist calls `Post.new`, then runs through the
|
124
|
+
attributes in your blueprint, calling the block for each attribute to generate
|
125
|
+
a value. It then saves and reloads the Post. (It throws an exception if the
|
126
|
+
Post can't be saved.)
|
127
|
+
|
128
|
+
You can override values defined in the blueprint by passing a hash to make:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
Post.make!(title: 'A Specific Title')
|
132
|
+
```
|
133
|
+
|
134
|
+
If you want to generate an object without saving it to the database, replace
|
135
|
+
`make!` with `make`.
|
136
|
+
|
137
|
+
### Unique Attributes
|
138
|
+
|
139
|
+
For attributes that need to be unique, you can call the `sn` method from
|
140
|
+
within the attribute block to get a unique serial number for the object.
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
User.blueprint do
|
144
|
+
username { "user-#{sn}" }
|
145
|
+
end
|
146
|
+
```
|
147
|
+
|
148
|
+
### Associations
|
149
|
+
|
150
|
+
If your object needs associated objects, you can generate them like this:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
Comment.blueprint do
|
154
|
+
post { Post.make }
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
Calling `Comment.make!` will construct a Comment and its associated Post, and
|
159
|
+
save both.
|
160
|
+
|
161
|
+
Machinist is smart enough to look at the association and work out what sort of
|
162
|
+
object it needs to create, so you can shorten the above blueprint to:
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
Comment.blueprint do
|
166
|
+
post
|
167
|
+
end
|
168
|
+
```
|
169
|
+
|
170
|
+
If you want to override the value for post when constructing the comment, you
|
171
|
+
can do this:
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
post = Post.make(title: 'A particular title')
|
175
|
+
comment = Comment.make(post: post)
|
176
|
+
```
|
177
|
+
|
178
|
+
For `has_many` and `has_and_belongs_to_many` associations, you can create
|
179
|
+
multiple associated objects like this:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
Post.blueprint do
|
183
|
+
comments(3) # Makes 3 comments.
|
184
|
+
end
|
185
|
+
```
|
186
|
+
|
187
|
+
### Named Blueprints
|
188
|
+
|
189
|
+
Named blueprints let you define variations on an object. For example, suppose
|
190
|
+
some of your Users are administrators:
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
User.blueprint do
|
194
|
+
name { "User #{sn}" }
|
195
|
+
email { "user-#{sn}@example.com" }
|
196
|
+
end
|
197
|
+
|
198
|
+
User.blueprint(:admin) do
|
199
|
+
name { "Admin User #{sn}" }
|
200
|
+
admin { true }
|
201
|
+
end
|
202
|
+
```
|
203
|
+
|
204
|
+
Calling:
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
User.make!(:admin)
|
208
|
+
```
|
209
|
+
|
210
|
+
will use the `:admin` blueprint.
|
211
|
+
|
212
|
+
Named blueprints call the default blueprint to set any attributes not
|
213
|
+
specifically provided, so in this example the `email` attribute will still be
|
214
|
+
generated even for an admin user.
|
215
|
+
|
216
|
+
You must define a default blueprint for any class that has a named blueprint,
|
217
|
+
even if the default blueprint is empty.
|
218
|
+
|
219
|
+
### Blueprints on Plain Old Ruby Objects
|
220
|
+
|
221
|
+
Machinist also works with plain old Ruby objects. Let's say you have a class like:
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
class Post
|
225
|
+
extend Machinist::Machinable
|
226
|
+
|
227
|
+
attr_accessor :title
|
228
|
+
attr_accessor :body
|
229
|
+
end
|
230
|
+
```
|
231
|
+
|
232
|
+
You can blueprint the Post class just like anything else:
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
Post.blueprint do
|
236
|
+
title { 'A title!' }
|
237
|
+
body { 'A body!' }
|
238
|
+
end
|
239
|
+
```
|
240
|
+
|
241
|
+
And `Post.make` will construct a new Post.
|
242
|
+
|
243
|
+
### Other Tricks
|
244
|
+
|
245
|
+
You can refer to already assigned attributes when constructing a new attribute:
|
246
|
+
|
247
|
+
```ruby
|
248
|
+
Post.blueprint do
|
249
|
+
author { "Author #{sn}" }
|
250
|
+
body { "Post by #{object.author}" }
|
251
|
+
end
|
252
|
+
```
|
253
|
+
|
254
|
+
### More Details
|
255
|
+
|
256
|
+
Read the code! No, really. I wrote this code to be read.
|
257
|
+
|
258
|
+
Check out [the specs](https://github.com/dominicsayers/machinist/tree/master/spec), starting with [the spec for Machinable](https://github.com/dominicsayers/machinist/blob/master/spec/machinable_spec.rb).
|
259
|
+
|
260
|
+
## Developing
|
261
|
+
|
262
|
+
The Machinist specs and source code were written to be read, and I'm pretty
|
263
|
+
happy with them. Don't be afraid to have a look under the hood!
|
264
|
+
|
265
|
+
If you want to submit a patch:
|
266
|
+
|
267
|
+
- Fork the project.
|
268
|
+
- Make your feature addition or bug fix.
|
269
|
+
- Add tests for it. This is important so I don't break it in a
|
270
|
+
future version unintentionally.
|
271
|
+
- Commit, do not mess with rakefile, version, or history.
|
272
|
+
(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)
|
273
|
+
- Send me a pull request. Bonus points for topic branches.
|
274
|
+
|
275
|
+
## Contributors
|
276
|
+
|
277
|
+
Machinist was maintained by Pete Yandell ([pete@notahat.com](mailto:pete@notahat.com), [@notahat](http://twitter.com/notahat))
|
278
|
+
|
279
|
+
Other contributors include:
|
280
|
+
|
281
|
+
[Marcos Arias](http://github.com/yizzreel),
|
282
|
+
[Jack Dempsey](http://github.com/jackdempsey),
|
283
|
+
[Jeremy Durham](http://github.com/jeremydurham),
|
284
|
+
[Clinton Forbes](http://github.com/clinton),
|
285
|
+
[Perryn Fowler](http://github.com/perryn),
|
286
|
+
[Niels Ganser](http://github.com/Nielsomat),
|
287
|
+
[Jeremy Grant](http://github.com/jeremygrant),
|
288
|
+
[Jon Guymon](http://github.com/gnarg),
|
289
|
+
[James Healy](http://github.com/yob),
|
290
|
+
[Ben Hoskings](http://github.com/benhoskings),
|
291
|
+
[Evan David Light](http://github.com/elight),
|
292
|
+
[Chris Lloyd](http://github.com/chrislloyd),
|
293
|
+
[Adam Meehan](http://github.com/adzap),
|
294
|
+
[Kyle Neath](http://github.com/kneath),
|
295
|
+
[Lawrence Pit](http://github.com/lawrencepit),
|
296
|
+
[Xavier Shay](http://github.com/xaviershay),
|
297
|
+
[T.J. Sheehy](http://github.com/tjsheehy),
|
298
|
+
[Roland Swingler](http://github.com/knaveofdiamonds),
|
299
|
+
[Gareth Townsend](http://github.com/quamen),
|
300
|
+
[Matt Wastrodowski](http://github.com/towski),
|
301
|
+
[Ian White](http://github.com/ianwhite),
|
302
|
+
[Dominic Sayers](https://github.com/dominicsayers)
|
303
|
+
|
304
|
+
Thanks to Thoughtbot's [Factory
|
305
|
+
Girl](http://github.com/thoughtbot/factory_girl/tree/master). Machinist was
|
306
|
+
written because I loved the idea behind Factory Girl, but I thought the
|
307
|
+
philosophy wasn't quite right, and I hated the syntax.
|