object-daddy 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +130 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +312 -0
- data/Rakefile +34 -0
- data/VERSION +1 -0
- data/lib/generators/object_daddy_generator.rb +8 -0
- data/lib/object-daddy.rb +1 -0
- data/lib/object_daddy/railtie.rb +19 -0
- data/lib/object_daddy.rb +266 -0
- data/object-daddy.gemspec +83 -0
- data/spec/generators/object_daddy_generator_spec.rb +124 -0
- data/spec/object_daddy_spec.rb +1024 -0
- data/spec/resources/schema +55 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/tmp/.git_sucks +0 -0
- metadata +185 -0
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "rspec", "~> 2.8.0"
|
10
|
+
gem "rdoc", "~> 3.12"
|
11
|
+
gem "bundler", "~> 1.0.0"
|
12
|
+
gem "jeweler", "~> 1.8.3"
|
13
|
+
gem "rails", "~> 3.1.4"
|
14
|
+
gem "generator_spec"
|
15
|
+
gem "sqlite3"
|
16
|
+
gem "rspec-rails"
|
17
|
+
gem "pry"
|
18
|
+
gem "mocha"
|
19
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
actionmailer (3.1.4)
|
5
|
+
actionpack (= 3.1.4)
|
6
|
+
mail (~> 2.3.0)
|
7
|
+
actionpack (3.1.4)
|
8
|
+
activemodel (= 3.1.4)
|
9
|
+
activesupport (= 3.1.4)
|
10
|
+
builder (~> 3.0.0)
|
11
|
+
erubis (~> 2.7.0)
|
12
|
+
i18n (~> 0.6)
|
13
|
+
rack (~> 1.3.6)
|
14
|
+
rack-cache (~> 1.1)
|
15
|
+
rack-mount (~> 0.8.2)
|
16
|
+
rack-test (~> 0.6.1)
|
17
|
+
sprockets (~> 2.0.3)
|
18
|
+
activemodel (3.1.4)
|
19
|
+
activesupport (= 3.1.4)
|
20
|
+
builder (~> 3.0.0)
|
21
|
+
i18n (~> 0.6)
|
22
|
+
activerecord (3.1.4)
|
23
|
+
activemodel (= 3.1.4)
|
24
|
+
activesupport (= 3.1.4)
|
25
|
+
arel (~> 2.2.3)
|
26
|
+
tzinfo (~> 0.3.29)
|
27
|
+
activeresource (3.1.4)
|
28
|
+
activemodel (= 3.1.4)
|
29
|
+
activesupport (= 3.1.4)
|
30
|
+
activesupport (3.1.4)
|
31
|
+
multi_json (~> 1.0)
|
32
|
+
arel (2.2.3)
|
33
|
+
builder (3.0.0)
|
34
|
+
coderay (1.0.6)
|
35
|
+
diff-lcs (1.1.3)
|
36
|
+
erubis (2.7.0)
|
37
|
+
generator_spec (0.8.5)
|
38
|
+
rails (>= 3.0, < 4.0)
|
39
|
+
rspec-rails
|
40
|
+
git (1.2.5)
|
41
|
+
hike (1.2.1)
|
42
|
+
i18n (0.6.0)
|
43
|
+
jeweler (1.8.3)
|
44
|
+
bundler (~> 1.0)
|
45
|
+
git (>= 1.2.5)
|
46
|
+
rake
|
47
|
+
rdoc
|
48
|
+
json (1.6.6)
|
49
|
+
mail (2.3.3)
|
50
|
+
i18n (>= 0.4.0)
|
51
|
+
mime-types (~> 1.16)
|
52
|
+
treetop (~> 1.4.8)
|
53
|
+
metaclass (0.0.1)
|
54
|
+
method_source (0.7.1)
|
55
|
+
mime-types (1.18)
|
56
|
+
mocha (0.10.5)
|
57
|
+
metaclass (~> 0.0.1)
|
58
|
+
multi_json (1.2.0)
|
59
|
+
polyglot (0.3.3)
|
60
|
+
pry (0.9.8.4)
|
61
|
+
coderay (~> 1.0.5)
|
62
|
+
method_source (~> 0.7.1)
|
63
|
+
slop (>= 2.4.4, < 3)
|
64
|
+
rack (1.3.6)
|
65
|
+
rack-cache (1.2)
|
66
|
+
rack (>= 0.4)
|
67
|
+
rack-mount (0.8.3)
|
68
|
+
rack (>= 1.0.0)
|
69
|
+
rack-ssl (1.3.2)
|
70
|
+
rack
|
71
|
+
rack-test (0.6.1)
|
72
|
+
rack (>= 1.0)
|
73
|
+
rails (3.1.4)
|
74
|
+
actionmailer (= 3.1.4)
|
75
|
+
actionpack (= 3.1.4)
|
76
|
+
activerecord (= 3.1.4)
|
77
|
+
activeresource (= 3.1.4)
|
78
|
+
activesupport (= 3.1.4)
|
79
|
+
bundler (~> 1.0)
|
80
|
+
railties (= 3.1.4)
|
81
|
+
railties (3.1.4)
|
82
|
+
actionpack (= 3.1.4)
|
83
|
+
activesupport (= 3.1.4)
|
84
|
+
rack-ssl (~> 1.3.2)
|
85
|
+
rake (>= 0.8.7)
|
86
|
+
rdoc (~> 3.4)
|
87
|
+
thor (~> 0.14.6)
|
88
|
+
rake (0.9.2.2)
|
89
|
+
rdoc (3.12)
|
90
|
+
json (~> 1.4)
|
91
|
+
rspec (2.8.0)
|
92
|
+
rspec-core (~> 2.8.0)
|
93
|
+
rspec-expectations (~> 2.8.0)
|
94
|
+
rspec-mocks (~> 2.8.0)
|
95
|
+
rspec-core (2.8.0)
|
96
|
+
rspec-expectations (2.8.0)
|
97
|
+
diff-lcs (~> 1.1.2)
|
98
|
+
rspec-mocks (2.8.0)
|
99
|
+
rspec-rails (2.8.1)
|
100
|
+
actionpack (>= 3.0)
|
101
|
+
activesupport (>= 3.0)
|
102
|
+
railties (>= 3.0)
|
103
|
+
rspec (~> 2.8.0)
|
104
|
+
slop (2.4.4)
|
105
|
+
sprockets (2.0.3)
|
106
|
+
hike (~> 1.2)
|
107
|
+
rack (~> 1.0)
|
108
|
+
tilt (~> 1.1, != 1.3.0)
|
109
|
+
sqlite3 (1.3.5)
|
110
|
+
thor (0.14.6)
|
111
|
+
tilt (1.3.3)
|
112
|
+
treetop (1.4.10)
|
113
|
+
polyglot
|
114
|
+
polyglot (>= 0.3.1)
|
115
|
+
tzinfo (0.3.32)
|
116
|
+
|
117
|
+
PLATFORMS
|
118
|
+
ruby
|
119
|
+
|
120
|
+
DEPENDENCIES
|
121
|
+
bundler (~> 1.0.0)
|
122
|
+
generator_spec
|
123
|
+
jeweler (~> 1.8.3)
|
124
|
+
mocha
|
125
|
+
pry
|
126
|
+
rails (~> 3.1.4)
|
127
|
+
rdoc (~> 3.12)
|
128
|
+
rspec (~> 2.8.0)
|
129
|
+
rspec-rails
|
130
|
+
sqlite3
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2007 Flawed Logic, OG Consulting, Rick Bradley, Yossef Mendelssohn
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,312 @@
|
|
1
|
+
Object Daddy
|
2
|
+
============
|
3
|
+
_Version 1.0.0 (April 6, 2012)_
|
4
|
+
|
5
|
+
__Authors:__ [Rick Bradley](mailto:blogicx@rickbradley.com), [Yossef Mendelssohn](mailto:ymendel@pobox.com), [Jeremy Holland](mailto:jeremy@jeremypholland.com)
|
6
|
+
|
7
|
+
__Gem Maintainer:__ [Jeremy Holland](mailto:jeremy@jeremypholland.com)
|
8
|
+
|
9
|
+
__Copyright:__ Copyright (c) 2007, Flawed Logic, OG Consulting, Rick Bradley, Yossef Mendelssohn
|
10
|
+
|
11
|
+
__License:__ MIT License. See LICENSE.txt file for more details.
|
12
|
+
|
13
|
+
Object Daddy is a library (as well as a Ruby on Rails plugin) designed to
|
14
|
+
assist in automating testing of large collections of objects, especially webs
|
15
|
+
of ActiveRecord models. It is a descendent of the "Object Mother" pattern for
|
16
|
+
creating objects for testing, and is related to the concept of an "object
|
17
|
+
exemplar" or _stereotype_.
|
18
|
+
|
19
|
+
**WARNING** This code is very much at an _alpha_ development stage. Usage, APIs,
|
20
|
+
etc., are all subject to change.
|
21
|
+
|
22
|
+
See [http://b.logi.cx/2007/11/26/object-daddy](http://b.logi.cx/2007/11/26/object-daddy) for inspiration, historical drama, and too much reading.
|
23
|
+
|
24
|
+
## Installation
|
25
|
+
|
26
|
+
Add the following to your Gemfile and run `bundle install`
|
27
|
+
|
28
|
+
group :development, :test do
|
29
|
+
gem 'object-daddy'
|
30
|
+
end
|
31
|
+
|
32
|
+
Once installed, to set up your exemplars directory, run `rails g object-daddy`
|
33
|
+
|
34
|
+
## Using Object Daddy
|
35
|
+
|
36
|
+
Object Daddy adds a `.generate` method to every ActiveRecord model which can be
|
37
|
+
called to generate a valid instance object of that model class, for use in
|
38
|
+
testing:
|
39
|
+
|
40
|
+
it "should have a comment for every forum the user posts to" do
|
41
|
+
@user = User.generate
|
42
|
+
@post = Post.generate
|
43
|
+
@post.comments << Comment.generate
|
44
|
+
@user.should have(1).comments
|
45
|
+
end
|
46
|
+
|
47
|
+
This allows us to generate custom model objects without relying on fixtures,
|
48
|
+
and without knowing, in our various widespread tests and specs, the details of
|
49
|
+
creating a User, Post, Comment, etc. Not having to know this information means
|
50
|
+
the information isn't coded into dozens (or hundreds) of tests, and won't need
|
51
|
+
to be changed when the User (Post, Comment, ...) model is refactored later.
|
52
|
+
|
53
|
+
Object Daddy will identify associated classes that need to be instantiated to
|
54
|
+
make the main model valid. E.g., given the following models:
|
55
|
+
|
56
|
+
class User < ActiveRecord::Base
|
57
|
+
belongs_to :login
|
58
|
+
validates :login, :presence => true
|
59
|
+
end
|
60
|
+
|
61
|
+
class Login < ActiveRecord::Base
|
62
|
+
has_one :user
|
63
|
+
end
|
64
|
+
|
65
|
+
A call to `User.generate` will also make a call to `Login.generate` so that
|
66
|
+
`User#login` is present, and therefore valid.
|
67
|
+
|
68
|
+
If all models were able to be created in a valid form by the default Model.new
|
69
|
+
call with no knowledge of the model itself, there'd be no need for Object
|
70
|
+
Daddy. So, when we deal with models which have validity requirements,
|
71
|
+
requiring fields which have format constraints, we need a means of expressing
|
72
|
+
how to create those models -- how to satisfy those validity constraints.
|
73
|
+
|
74
|
+
Object Daddy provides a `generator_for` method which allows the developer to
|
75
|
+
specify, for a specific model attribute, how to make a valid value. Note that
|
76
|
+
`validates_uniqueness_of` can require that, even if we make 100,000 instances
|
77
|
+
of a model that unique attributes cannot have the same values.
|
78
|
+
|
79
|
+
Object Daddy's `generator_for` method can take three main forms corresponding to
|
80
|
+
the means of finding a value for the associated attribute: a block, a method
|
81
|
+
call, or using a generator class.
|
82
|
+
|
83
|
+
class User < ActiveRecord::Base
|
84
|
+
validates :email,
|
85
|
+
:presence => true,
|
86
|
+
:uniqueness => true,
|
87
|
+
:format => {
|
88
|
+
:with => /^[-a-z_+0-9.]+@(?:[-a-z_+0-9.]\.)+[a-z]+$/i
|
89
|
+
}
|
90
|
+
validates :username,
|
91
|
+
:presence => true,
|
92
|
+
:format => {
|
93
|
+
:with => /^[a-z0-9_]{4,12}$/i
|
94
|
+
}
|
95
|
+
|
96
|
+
generator_for :email, :start => 'test@domain.com' do |prev|
|
97
|
+
user, domain = prev.split('@')
|
98
|
+
user.succ + '@' + domain
|
99
|
+
end
|
100
|
+
|
101
|
+
generator_for :username, :method => :next_user
|
102
|
+
|
103
|
+
generator_for :ssn, :class => SSNGenerator
|
104
|
+
|
105
|
+
def self.next_user
|
106
|
+
@last_username ||= 'testuser'
|
107
|
+
@last_username.succ
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class SSNGenerator
|
112
|
+
def self.next
|
113
|
+
@last ||= '000-00-0000'
|
114
|
+
@last = ("%09d" % (@last.gsub('-', '').to_i + 1)).sub(/^(\d{3})(\d{2})(\d{4})$/, '\1-\2-\3')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
Note that the block method of invocation (as used with _:email_ above) takes an
|
119
|
+
optional _:start_ argument, to specify the value of that attribute on the first
|
120
|
+
run. The block will be called thereafter with the previous value of the
|
121
|
+
attribute and will generate the next attribute value to be used.
|
122
|
+
|
123
|
+
A simple default block is provided for any generator with a :start value.
|
124
|
+
|
125
|
+
class User < ActiveRecord::Base
|
126
|
+
generator_for :name, :start => 'Joe' do |prev|
|
127
|
+
prev.succ
|
128
|
+
end
|
129
|
+
|
130
|
+
generator_for :name, :start => 'Joe' # equivalent to the above
|
131
|
+
end
|
132
|
+
|
133
|
+
The _:method_ form takes a symbol naming a class method in the model class to be
|
134
|
+
called to generate a new value for the attribute in question. If the method
|
135
|
+
takes a single argument, it will act much like the block method of invocation,
|
136
|
+
being called with the previous value and generating the next.
|
137
|
+
|
138
|
+
The _:class_ form calls the .next class method on the named class to generate a
|
139
|
+
new value for the attribute in question.
|
140
|
+
|
141
|
+
The argument (previous value) to the block invocation form can be omitted if
|
142
|
+
it's going to be ignored, and simple invocation forms are provided for literal
|
143
|
+
values.
|
144
|
+
|
145
|
+
class User < ActiveRecord::Base
|
146
|
+
generator_for(:start_time) { Time.now }
|
147
|
+
generator_for :name, 'Joe'
|
148
|
+
generator_for :age => 25
|
149
|
+
end
|
150
|
+
|
151
|
+
The developer would then simply call `User.generate` when testing.
|
152
|
+
|
153
|
+
If some attribute values are known (or are being controlled during testing)
|
154
|
+
then these can simply be passed in to `.generate`:
|
155
|
+
|
156
|
+
@bad_login = Login.generate(:expiry => 1.week.ago)
|
157
|
+
@expired_user = User.generate(:login => @bad_login)
|
158
|
+
|
159
|
+
A `.generate!` method is also provided. The _generate/generate!_ pair of methods
|
160
|
+
can be thought of as analogs to create/create!, one merely providing an instance
|
161
|
+
that may or may not be valid and the other raising an exception if any
|
162
|
+
problem comes up.
|
163
|
+
|
164
|
+
Finally, a `.spawn` method is provided that only gives a new, unsaved object. Note
|
165
|
+
that this is the only method of the three that is available if you happen to be
|
166
|
+
using Object Daddy outside of Rails.
|
167
|
+
|
168
|
+
## Exemplars
|
169
|
+
|
170
|
+
In the examples given above we are using `generator_for` in the bodies of the
|
171
|
+
models themselves. Given that Object Daddy is primarily geared towards
|
172
|
+
annotating models with information useful for testing, we anticipate that
|
173
|
+
`generator_for` should not normally be included inline in models. Rather, we
|
174
|
+
will provide a place where model classes can be re-opened and `generator_for`
|
175
|
+
calls (and support methods) can be written without polluting the model files
|
176
|
+
with Object Daddy information.
|
177
|
+
|
178
|
+
when the Object Daddy generator is run, it will create
|
179
|
+
*RAILS_ROOT/spec/exemplars/* as a place to hold __exemplar__ files for Rails model
|
180
|
+
classes. (We are seeking perhaps some better terminology)
|
181
|
+
|
182
|
+
An __exemplar__ for the User model would then be found in
|
183
|
+
*RAILS_ROOT/spec/exemplars/user_exemplar.rb* (when you are using a testing tool
|
184
|
+
which works from *RAILS_ROOT/test*, Object Daddy will create
|
185
|
+
*RAILS_ROOT/test/exemplars* and look for your exemplars in that directory
|
186
|
+
instead). Exemplar files are completely optional, and no model need have
|
187
|
+
exemplar files. The `.generate` method will still exist and be callable, and
|
188
|
+
`generator_for` can be declared in the model files themselves. If an exemplar
|
189
|
+
file is available when `.generate` is called on a model, the exemplar file will
|
190
|
+
be loaded and used. An example *user_exemplar.rb* appears below:
|
191
|
+
|
192
|
+
require 'ssn_generator'
|
193
|
+
|
194
|
+
class User < ActiveRecord::Base
|
195
|
+
generator_for :email, :start => 'test@domain.com' do |prev|
|
196
|
+
user, domain = prev.split('@')
|
197
|
+
user.succ + '@' + domain
|
198
|
+
end
|
199
|
+
|
200
|
+
generator_for :username, :method => :next_user
|
201
|
+
|
202
|
+
generator_for :ssn, :class => SSNGenerator
|
203
|
+
|
204
|
+
def self.next_user
|
205
|
+
@last_username ||= 'testuser'
|
206
|
+
@last_username.succ
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
## Blocks
|
211
|
+
|
212
|
+
The `spawn`, `generate` and `generate!` methods can all accept a block, to which
|
213
|
+
they'll yield the generated object. This provides a nice scoping mechanism in
|
214
|
+
your code examples. Consider:
|
215
|
+
|
216
|
+
describe "admin user" do
|
217
|
+
it "should be authorized to create company profiles"
|
218
|
+
admin_user = User.generate!
|
219
|
+
admin_user.activate!
|
220
|
+
admin_user.add_role("admin")
|
221
|
+
|
222
|
+
admin_user.should be_authorized(:create, Company)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
This could be refactored to:
|
227
|
+
|
228
|
+
describe "admin user" do
|
229
|
+
it "should be authorized to create company profiles" do
|
230
|
+
admin_user = User.generate! do |user|
|
231
|
+
user.activate!
|
232
|
+
user.add_role("admin")
|
233
|
+
end
|
234
|
+
|
235
|
+
admin_user.should be_authorized(:create, Company)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
Or:
|
240
|
+
|
241
|
+
describe "admin user" do
|
242
|
+
it "should be authorized to create company profiles"
|
243
|
+
User.generate! do |user|
|
244
|
+
user.activate!
|
245
|
+
user.add_role("admin")
|
246
|
+
end.should be_authorized(:create, Company)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
Or even:
|
251
|
+
|
252
|
+
describe "admin user" do
|
253
|
+
def admin_user
|
254
|
+
@admin_user ||= User.generate! do |user|
|
255
|
+
user.activate!
|
256
|
+
user.add_role("admin")
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should be authorized to create company profiles"
|
261
|
+
admin_user.should be_authorized(:create, Company)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
This last refactoring allows you to reuse the admin_user method across
|
266
|
+
multiple code examples, balancing DRY with local data.
|
267
|
+
|
268
|
+
## Object Daddy and Fixtures
|
269
|
+
|
270
|
+
While Object Daddy is meant to obviate the hellish devilspawn that are test
|
271
|
+
fixtures, Object Daddy should work alongside fixtures just fine. To each his
|
272
|
+
own, I suppose.
|
273
|
+
|
274
|
+
## Known Issues
|
275
|
+
|
276
|
+
The simple invocation forms for `generator_for` when using literal values do not
|
277
|
+
work if the literal value is a Hash. Don't do that.
|
278
|
+
|
279
|
+
class User < ActiveRecord::Base
|
280
|
+
generator_for :thing_hash, { 'some key' => 'some value' }
|
281
|
+
generator_for :other_hash => { 'other key' => 'other value' }
|
282
|
+
end
|
283
|
+
|
284
|
+
I'm not sure why this would even ever come up, but seriously, don't.
|
285
|
+
|
286
|
+
Required `belongs_to` associations are automatically generated when generating an instance,
|
287
|
+
but only if necessary.
|
288
|
+
|
289
|
+
class Category < ActiveRecord::Base
|
290
|
+
has_many :items
|
291
|
+
end
|
292
|
+
|
293
|
+
class Item < ActiveRecord::Base
|
294
|
+
belongs_to :category
|
295
|
+
validates :category, :presence => true
|
296
|
+
end
|
297
|
+
|
298
|
+
`Item.generate` will generate a new category, but `some_category.items.generate` will not.
|
299
|
+
Unless, of course, you are foolish enough to define a generator in the exemplar.
|
300
|
+
|
301
|
+
class Item
|
302
|
+
generator_for(:category) { Category.generate }
|
303
|
+
end
|
304
|
+
|
305
|
+
Once again, don't do that.
|
306
|
+
|
307
|
+
## Rails _surprises_
|
308
|
+
|
309
|
+
Due to the way Rails handles associations, cascading generations (as a result of
|
310
|
+
required associations) are always generated-and-saved, even if the original generation
|
311
|
+
call was a mere `spawn` (`new`). This may come as a surprise, but it would probably be more
|
312
|
+
of a surprise if `User.spawn.save` and `User.generate` weren't comparable.
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "object-daddy"
|
18
|
+
gem.homepage = "http://github.com/awebneck/object_daddy"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Kill Fixtures}
|
21
|
+
gem.description = %Q{Object Daddy is a library (as well as a Ruby on Rails plugin) designed to assist in automating testing of large collections of objects, especially webs of ActiveRecord models. It is a descendent of the "Object Mother" pattern for creating objects for testing, and is related to the concept of an "object exemplar" or stereotype.}
|
22
|
+
gem.email = ["blogicx@rickbradley.com", "ymendel@pobox.com", "jeremy@jeremypholland.com"]
|
23
|
+
gem.authors = ["Rick Bradley", "Yossef Mendelssohn", "Jeremy Holland"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rspec/core'
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
task :default => :spec
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class ObjectDaddyGenerator < Rails::Generators::Base
|
2
|
+
desc "create exemplars directory"
|
3
|
+
def create_exemplars_dir
|
4
|
+
testfw = File.exists?("#{destination_root}/test") ? "test" : "spec"
|
5
|
+
empty_directory "#{testfw}/exemplars"
|
6
|
+
create_file "#{testfw}/exemplars/.gitkeep", "git sucks"
|
7
|
+
end
|
8
|
+
end
|
data/lib/object-daddy.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'object_daddy'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ObjectDaddy
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
railtie_name :object_daddy
|
4
|
+
initializer 'object_daddy.extend.activerecord' do
|
5
|
+
::ActiveSupport.on_load :active_record do
|
6
|
+
class ::ActiveRecord::Base
|
7
|
+
def self.inherited_with_object_daddy(subclass)
|
8
|
+
self.inherited_without_object_daddy(subclass)
|
9
|
+
subclass.send(:include, ObjectDaddy) unless subclass < ObjectDaddy
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
alias_method_chain :inherited, :object_daddy
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|