judit-pickle 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +20 -0
- data/Gemfile.lock +98 -0
- data/History.txt +409 -0
- data/License.txt +20 -0
- data/README.rdoc +367 -0
- data/Rakefile +20 -0
- data/Rakefile.d/cucumber.rake +24 -0
- data/Rakefile.d/jeweler.rake +23 -0
- data/Rakefile.d/rcov.rake +18 -0
- data/Rakefile.d/rspec.rake +7 -0
- data/Rakefile.d/yard.rake +5 -0
- data/Todo.txt +3 -0
- data/VERSION +1 -0
- data/features/app/app.rb +122 -0
- data/features/app/blueprints.rb +11 -0
- data/features/app/factories.rb +23 -0
- data/features/app/views/notifier/email.erb +1 -0
- data/features/app/views/notifier/user_email.erb +6 -0
- data/features/email/email.feature +64 -0
- data/features/generator/generators.feature +59 -0
- data/features/path/models_page.feature +44 -0
- data/features/path/named_route_page.feature +10 -0
- data/features/pickle/create_from_active_record.feature +76 -0
- data/features/pickle/create_from_factory_girl.feature +63 -0
- data/features/pickle/create_from_machinist.feature +39 -0
- data/features/step_definitions/email_steps.rb +63 -0
- data/features/step_definitions/extra_email_steps.rb +7 -0
- data/features/step_definitions/fork_steps.rb +4 -0
- data/features/step_definitions/generator_steps.rb +46 -0
- data/features/step_definitions/path_steps.rb +14 -0
- data/features/step_definitions/pickle_steps.rb +100 -0
- data/features/step_definitions/raise_error_steps.rb +3 -0
- data/features/support/email.rb +21 -0
- data/features/support/env.rb +52 -0
- data/features/support/paths.rb +47 -0
- data/features/support/pickle.rb +26 -0
- data/features/support/pickle_app.rb +4 -0
- data/init.rb +0 -0
- data/lib/generators/pickle_generator.rb +69 -0
- data/lib/pickle/adapter.rb +137 -0
- data/lib/pickle/adapters/active_record.rb +57 -0
- data/lib/pickle/adapters/data_mapper.rb +42 -0
- data/lib/pickle/adapters/mongoid.rb +44 -0
- data/lib/pickle/config.rb +49 -0
- data/lib/pickle/email/parser.rb +18 -0
- data/lib/pickle/email/world.rb +13 -0
- data/lib/pickle/email.rb +77 -0
- data/lib/pickle/parser/matchers.rb +87 -0
- data/lib/pickle/parser.rb +65 -0
- data/lib/pickle/path/world.rb +5 -0
- data/lib/pickle/path.rb +45 -0
- data/lib/pickle/session/parser.rb +34 -0
- data/lib/pickle/session.rb +205 -0
- data/lib/pickle/version.rb +9 -0
- data/lib/pickle/world.rb +14 -0
- data/lib/pickle.rb +26 -0
- data/pickle.gemspec +134 -0
- data/rails_generators/pickle/pickle_generator.rb +33 -0
- data/rails_generators/pickle/templates/email.rb +21 -0
- data/rails_generators/pickle/templates/email_steps.rb +63 -0
- data/rails_generators/pickle/templates/paths.rb +47 -0
- data/rails_generators/pickle/templates/pickle.rb +28 -0
- data/rails_generators/pickle/templates/pickle_steps.rb +100 -0
- data/spec/pickle/adapter_spec.rb +186 -0
- data/spec/pickle/config_spec.rb +109 -0
- data/spec/pickle/email/parser_spec.rb +51 -0
- data/spec/pickle/email_spec.rb +166 -0
- data/spec/pickle/parser/matchers_spec.rb +70 -0
- data/spec/pickle/parser_spec.rb +161 -0
- data/spec/pickle/path_spec.rb +101 -0
- data/spec/pickle/session_spec.rb +434 -0
- data/spec/pickle_spec.rb +24 -0
- data/spec/spec_helper.rb +8 -0
- metadata +199 -0
data/README.rdoc
ADDED
@@ -0,0 +1,367 @@
|
|
1
|
+
= pickle
|
2
|
+
|
3
|
+
Pickle gives you cucumber steps that create your models easily from factory-girl or
|
4
|
+
machinist factories/blueprints. You can also just use ActiveRecord as a factory but it's not as cool.
|
5
|
+
|
6
|
+
Pickle can make use of different ORMs for finding records. Currently ActiveRecord, DataMapper, MongoID adapters are
|
7
|
+
provided. More adapters welcome!
|
8
|
+
|
9
|
+
References to the models are stored in the current world, not necessarily for the purpose of checking the db
|
10
|
+
(although you could use it for that), but for enabling easy reference to urls, and for
|
11
|
+
building complex givens which require a bunch of models collaborating
|
12
|
+
|
13
|
+
== Quickstart
|
14
|
+
|
15
|
+
This is a quickstart guide for rails apps. Firstly, install {cucumber-rails}[http://github.com/aslakhellesoy/cucumber-rails], and its dependencies.
|
16
|
+
Then do the following:
|
17
|
+
|
18
|
+
=== Rails 3:
|
19
|
+
|
20
|
+
Add the gem to your Gemfile:
|
21
|
+
|
22
|
+
gem 'pickle'
|
23
|
+
|
24
|
+
Then install with:
|
25
|
+
|
26
|
+
bundle install
|
27
|
+
|
28
|
+
Discover the options for the generator:
|
29
|
+
|
30
|
+
rails g pickle --help
|
31
|
+
|
32
|
+
Run the generator, e.g:
|
33
|
+
|
34
|
+
rails g pickle --paths --email
|
35
|
+
|
36
|
+
=== For Rails 2:
|
37
|
+
|
38
|
+
Add the following to config/environments/cucumber:
|
39
|
+
|
40
|
+
config.gem 'pickle'
|
41
|
+
|
42
|
+
Install the gem with
|
43
|
+
|
44
|
+
rake gems:install RAILS_ENV=cucumber
|
45
|
+
|
46
|
+
Run the generator with:
|
47
|
+
|
48
|
+
script/generate pickle [paths] [email]
|
49
|
+
|
50
|
+
== Resources
|
51
|
+
|
52
|
+
<b>Github</b> for code: http://github.com/ianwhite/pickle
|
53
|
+
|
54
|
+
<b>Gemcutter</b> for the gem: http://gemcutter.org/gems/pickle
|
55
|
+
|
56
|
+
<b>Rdoc.info</b> for docs: http://rdoc.info/projects/ianwhite/pickle
|
57
|
+
|
58
|
+
<b>Google group</b> for questions: http://groups.google.com/group/pickle-cucumber
|
59
|
+
|
60
|
+
<b>Lighthouse</b> for bugs: http://ianwhite.lighthouseapp.com/projects/25941-pickle
|
61
|
+
|
62
|
+
<b>Railscast</b> presentation: http://railscasts.com/episodes/186-pickle-with-cucumber
|
63
|
+
|
64
|
+
<b>Blog articles</b>: {dynamic50: Integration testing with cucumber and pickle}[http://blog.dynamic50.com/index.php/2009/04/integration-testing-with-cucumber-and-pickle/], {rubyflare: pickle my cucumber}[http://rubyflare.com/2009/10/28/pickle-my-cucumber/]
|
65
|
+
|
66
|
+
|
67
|
+
== Using Pickle
|
68
|
+
|
69
|
+
Now have a look at <tt>features/step_definitions/pickle_steps.rb</tt>
|
70
|
+
|
71
|
+
If you want path steps and email steps then just add the 'paths' and/or 'email' options to the generator.
|
72
|
+
The code/steps will be written to <tt>features/env/paths.rb</tt> and
|
73
|
+
<tt>features/step_definitions/email_steps.rb</tt> respectively.
|
74
|
+
|
75
|
+
=== Using with plain ole Active Record, DataMapper or Mongoid
|
76
|
+
|
77
|
+
Pickle comes with ORM adapters for Active Record, DataMapper and Mongoid.
|
78
|
+
|
79
|
+
If you have a model called 'Post', with required fields 'title', and 'body', then you can now write
|
80
|
+
steps like this
|
81
|
+
|
82
|
+
Given a post exists with title: "My Post", body: "My body"
|
83
|
+
|
84
|
+
=== Using with factory-girl or machinist
|
85
|
+
|
86
|
+
But you're using Machinist or FactoryGirl right?! To leverage all of the factories/blueprints
|
87
|
+
you've written, you can just do stuff like
|
88
|
+
|
89
|
+
Given a user exists
|
90
|
+
And another user exists with role: "admin"
|
91
|
+
|
92
|
+
# later
|
93
|
+
Then a user should exist with name: "Fred"
|
94
|
+
And that user should be activated # this uses rspec predicate matchers
|
95
|
+
|
96
|
+
==== Machinist: require your blueprints and reset Shams
|
97
|
+
|
98
|
+
In your <tt>features/support/env.rb</tt> add the following lines at the bottom
|
99
|
+
|
100
|
+
require "#{Rails.root}/spec/blueprints" # or wherever they live
|
101
|
+
Before { Sham.reset } # reset Shams in between scenarios
|
102
|
+
|
103
|
+
==== FactoryGirl: make sure factories are loaded
|
104
|
+
|
105
|
+
In your config/environments/cucumber.rb file, make sure the factory-girl gem is included (unless it's installed as a plugin).
|
106
|
+
|
107
|
+
If that doesn't solve loading issues then require your factories.rb file directly in a file called 'features/support/factory_girl.rb'
|
108
|
+
|
109
|
+
# example features/support/factory_girl.rb
|
110
|
+
require File.dirname(__FILE__) + '/../../spec/factories'
|
111
|
+
|
112
|
+
=== Using with an ORM other than ActiveRecord, DataMapper, or Mongoid
|
113
|
+
|
114
|
+
Pickle can be used with any modelling library provided there is an adapter written for it.
|
115
|
+
|
116
|
+
Adapters are very simple and exist a module or class with the name "PickleAdapter" available to the class. For example
|
117
|
+
|
118
|
+
User.const_get(:PickleAdapter) #=> should return a pickle adapter
|
119
|
+
|
120
|
+
The Active Record and DataMapper ones can be found at
|
121
|
+
ActiveRecord::Base::PickleAdapter, DataMapper::Resource::PickleAdapter, Mongoid::Document::PickleAdapter respectively.
|
122
|
+
|
123
|
+
See how to implement one by looking at the ones provided in the pickle source in lib/pickle/adapters/*
|
124
|
+
|
125
|
+
=== Configuring Pickle
|
126
|
+
|
127
|
+
You can tell pickle to use another factory adapter (see Pickle::Adapter), or
|
128
|
+
create mappings from english expressions to pickle model names. You can also
|
129
|
+
override many of the options on the Pickle::Config object if you so choose.
|
130
|
+
|
131
|
+
In: <tt>features/support/pickle.rb</tt>
|
132
|
+
|
133
|
+
require 'pickle/world'
|
134
|
+
|
135
|
+
Pickle.configure do |config|
|
136
|
+
config.adapters = [:machinist, :active_record, YourOwnAdapterClass]
|
137
|
+
config.map 'me', 'myself', 'my', 'I', :to => 'user: "me"'
|
138
|
+
end
|
139
|
+
|
140
|
+
Out of the box pickle looks for machinist, factory-girl, then uses the ORM(s) that you're using to create models.
|
141
|
+
|
142
|
+
If you find that your steps aren't working with your factories, it's probably the case that your factory setup is not being included in your cucumber environment (see comments above regarding machinist and factory-girl).
|
143
|
+
|
144
|
+
== API
|
145
|
+
|
146
|
+
=== Steps
|
147
|
+
|
148
|
+
When you run <tt>script/generate pickle</tt> you get the following steps
|
149
|
+
|
150
|
+
==== Given steps
|
151
|
+
|
152
|
+
"Given <b>a model</b> exists", e.g.
|
153
|
+
|
154
|
+
Given a user exists
|
155
|
+
Given a user: "fred" exists
|
156
|
+
Given the user exists
|
157
|
+
|
158
|
+
"Given <b>a model</b> exists with <b>fields</b>", e.g.
|
159
|
+
|
160
|
+
Given a user exists with name: "Fred"
|
161
|
+
Given a user exists with name: "Fred", activated: false
|
162
|
+
|
163
|
+
This last step could be better expressed by using Machinist/FactoryGirl to create an activated user. Then you can do
|
164
|
+
|
165
|
+
Given an activated user exists with name: "Fred"
|
166
|
+
|
167
|
+
You can refer to other models in the fields
|
168
|
+
|
169
|
+
Given a user exists
|
170
|
+
And a post exists with author: the user
|
171
|
+
|
172
|
+
Given a person "fred" exists
|
173
|
+
And a person "ethel" exists
|
174
|
+
And a fatherhood exists with parent: person "fred", child: person "ethel"
|
175
|
+
|
176
|
+
This last step is given by the default pickle steps, but it would be better written as:
|
177
|
+
|
178
|
+
And "fred" is the father of "ethel"
|
179
|
+
|
180
|
+
It is expected that you'll need to expand upon the default pickle steps to make your features readable. To write the
|
181
|
+
above step, you could do something like:
|
182
|
+
|
183
|
+
Given /^"(\w+)" is the father of "(\w+)"$/ do |father, child|
|
184
|
+
Fatherhood.create! :father => model!("person: \"#{father}\""), :child => model!("person: \"#{child}\"")
|
185
|
+
end
|
186
|
+
|
187
|
+
"Given <b>n models</b> exist", e.g.
|
188
|
+
|
189
|
+
Given 10 users exist
|
190
|
+
|
191
|
+
"Given <b>n models</b> exist with <b>fields</b>", examples:
|
192
|
+
|
193
|
+
Given 10 users exist with activated: false
|
194
|
+
|
195
|
+
"Given the following <b>models</b> exist:", examples:
|
196
|
+
|
197
|
+
Given the following users exist
|
198
|
+
| name | activated |
|
199
|
+
| Fred | false |
|
200
|
+
| Ethel | true |
|
201
|
+
|
202
|
+
===== Named machinist blueprints
|
203
|
+
|
204
|
+
"Given <b> a <i>named</i> model</b> exists with <b>fields</b>"
|
205
|
+
|
206
|
+
The latest version of pickle supports {named machinist blueprints}[http://github.com/notahat/machinist/commit/d6492e6927a8aa1819926e48b22377171fd20496].
|
207
|
+
|
208
|
+
If you had the following blueprints:
|
209
|
+
|
210
|
+
User.blueprint do
|
211
|
+
name
|
212
|
+
email
|
213
|
+
end
|
214
|
+
|
215
|
+
User.blueprint(:super_admin) do
|
216
|
+
role { "admin" }
|
217
|
+
end
|
218
|
+
|
219
|
+
User.blueprint(:activated) do
|
220
|
+
activated { true }
|
221
|
+
end
|
222
|
+
|
223
|
+
You could create a user with pickle by simply adding the name of the blueprint before the model:
|
224
|
+
|
225
|
+
Given a super admin user exists
|
226
|
+
And an activated user exists with name: "Fred"
|
227
|
+
|
228
|
+
This is much nicer than having to set up common configurations in your steps all the time, and far more readable to boot.
|
229
|
+
|
230
|
+
|
231
|
+
==== Then steps
|
232
|
+
|
233
|
+
===== Asserting existence of models
|
234
|
+
|
235
|
+
"Then <b>a model</b> should exist", e.g.
|
236
|
+
|
237
|
+
Then a user should exist
|
238
|
+
|
239
|
+
"Then <b>a model</b> should exist with <b>fields</b>", e.g.
|
240
|
+
|
241
|
+
Then a user: "fred" should exist with name: "Fred" # we can label the found user for later use
|
242
|
+
|
243
|
+
You can use other models, booleans, numerics, and strings as fields
|
244
|
+
|
245
|
+
Then a person should exist with child: person "ethel"
|
246
|
+
Then a user should exist with activated: false
|
247
|
+
Then a user should exist with activated: true, email: "fred@gmail.com"
|
248
|
+
|
249
|
+
"Then <b>n models</b> should exist", e.g.
|
250
|
+
|
251
|
+
Then 10 events should exist
|
252
|
+
|
253
|
+
"Then <b>n models</b> should exist with <b>fields</b>", e.g.
|
254
|
+
|
255
|
+
Then 2 people should exist with father: person "fred"
|
256
|
+
|
257
|
+
"Then the following <b>models</b> exist". This allows the creation of multiple models
|
258
|
+
using a table syntax. Using a column with the singularized name of the model creates a referenceable model. E.g.
|
259
|
+
|
260
|
+
Then the following users exist:
|
261
|
+
| name | activated |
|
262
|
+
| Freddy | false |
|
263
|
+
|
264
|
+
Then the following users exist:
|
265
|
+
| user | name | activated |
|
266
|
+
| Fred | Freddy | false |
|
267
|
+
|
268
|
+
===== Asserting associations
|
269
|
+
|
270
|
+
One-to-one assocs: "Then <b>a model</b> should be <b>other model</b>'s <b>association</b>", e.g.
|
271
|
+
|
272
|
+
Then the person: "fred" should be person: "ethel"'s father
|
273
|
+
|
274
|
+
Many-to-one assocs: "Then <b>a model</b> should be [in|one of] <b>other model</b>'s <b>association</b>", e.g.
|
275
|
+
|
276
|
+
Then the person: "ethel" should be one of person: "fred"'s children
|
277
|
+
Then the comment should be in the post's comments
|
278
|
+
|
279
|
+
===== Asserting predicate methods
|
280
|
+
|
281
|
+
"Then <b>a model</b> should [be|have] [a|an] <b>predicate</b>", e.g.
|
282
|
+
|
283
|
+
Then the user should have a status # => user.status.should be_present
|
284
|
+
Then the user should have a stale password # => user.should have_stale_password
|
285
|
+
Then the car: "batmobile" should be fast # => car.should be_fast
|
286
|
+
|
287
|
+
"Then <b>a model</b> should not [be|have] [a|an] <b>predicate</b>", e.g.
|
288
|
+
|
289
|
+
Then person: "fred" should not be childless # => fred.should_not be_childless
|
290
|
+
|
291
|
+
=== Regexps for use in your own steps
|
292
|
+
|
293
|
+
By default you get some regexps available in the main namespace for use
|
294
|
+
in creating your own steps: `capture_model`, `capture_fields`, and others (see lib/pickle.rb)
|
295
|
+
|
296
|
+
(You can use any of the regexps that Pickle uses by using the Pickle.parser namespace, see
|
297
|
+
Pickle::Parser::Matchers for the methods available)
|
298
|
+
|
299
|
+
*capture_model*
|
300
|
+
|
301
|
+
Given /^#{capture_model} exists$/ do |model_name|
|
302
|
+
model(model_name).should_not == nil
|
303
|
+
end
|
304
|
+
|
305
|
+
Then /^I should be at the (.*?) page$/ |page|
|
306
|
+
if page =~ /#{capture_model}'s/
|
307
|
+
url_for(model($1))
|
308
|
+
else
|
309
|
+
# ...
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
Then /^#{capture_model} should be one of #{capture_model}'s posts$/ do |post, forum|
|
314
|
+
post = model!(post)
|
315
|
+
forum = model!(forum)
|
316
|
+
forum.posts.should include(post)
|
317
|
+
end
|
318
|
+
|
319
|
+
*capture_fields*
|
320
|
+
|
321
|
+
This is useful for setting attributes, and knows about pickle model names so that you
|
322
|
+
can build up composite objects with ease
|
323
|
+
|
324
|
+
Given /^#{capture_model} exists with #{capture_fields}$/ do |model_name, fields|
|
325
|
+
create_model(model_name, fields)
|
326
|
+
end
|
327
|
+
|
328
|
+
# example of use
|
329
|
+
Given a user exists
|
330
|
+
And a post exists with author: the user # this step will assign the above user as :author on the post
|
331
|
+
|
332
|
+
== Run the tests
|
333
|
+
|
334
|
+
To get all the dependencies required for developing pickle, do the following
|
335
|
+
|
336
|
+
bundle install
|
337
|
+
|
338
|
+
To run the specs do:
|
339
|
+
|
340
|
+
bundle exec rake spec
|
341
|
+
|
342
|
+
To run the features (rails 2.3 only ATM):
|
343
|
+
|
344
|
+
bundle exec rake cucumber
|
345
|
+
|
346
|
+
== Contributors
|
347
|
+
|
348
|
+
The following people have made Pickle better:
|
349
|
+
|
350
|
+
* {Marc Lee}[http://github.com/maleko]
|
351
|
+
* {Sebastian Zuchmanski}[http://github.com/sebcioz]
|
352
|
+
* {Paul Gideon Dann}[http://github.com/giddie]
|
353
|
+
* {Tom Meier}[http://github.com/tommeier]
|
354
|
+
* {Sean Hussey}[http://github.com/seanhussey]
|
355
|
+
* Brian Rose & Kevin Olsen
|
356
|
+
* {Christopher Darroch}[http://github.com/chrisdarroch]
|
357
|
+
* {Szymon Nowak}[http://github.com/szimek]
|
358
|
+
* {H.J. Blok}[http://github.com/hjblok]
|
359
|
+
* {Daniel Neighman}[http://github.com/hassox]
|
360
|
+
* {Josh Bassett}[http://github.com/nullobject]
|
361
|
+
* {Nick Rutherford}[http://github.com/nruth]
|
362
|
+
* {Tobi Knaup}[http://github.com/guenter]
|
363
|
+
* {Michael MacDonald}[http://github.com/schlick]
|
364
|
+
* {Michael Moen}[http://github.com/UnderpantsGnome]
|
365
|
+
* {Myron Marston}[http://github.com/myronmarston]
|
366
|
+
* {Stephan Hagemann}[http://github.com/xing]
|
367
|
+
* {Chris Flipse}[http://github.com/cflipse]
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
$:.unshift File.expand_path('lib')
|
2
|
+
|
3
|
+
# load given tasks file, reporting errors without failing
|
4
|
+
def load_tasks(tasks)
|
5
|
+
load tasks
|
6
|
+
rescue Exception => exception
|
7
|
+
$stderr << "** loading #{tasks.sub(File.expand_path('.'),'')} failed: "
|
8
|
+
case exception
|
9
|
+
when LoadError
|
10
|
+
$stderr << "to use, install the gems it requires\n"
|
11
|
+
else
|
12
|
+
$stderr << ([exception.message] + exception.backtrace[0..2]).join("\n ") << "\n\n"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Dir["Rakefile.d/*.rake"].sort.each {|t| load_tasks t}
|
17
|
+
|
18
|
+
task :default => :spec
|
19
|
+
|
20
|
+
task :ci => ['rcov:verify', 'cucumber']
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'cucumber/rake/task'
|
2
|
+
|
3
|
+
desc "Run features"
|
4
|
+
Cucumber::Rake::Task.new(:cucumber => [:cucumber_test_app]) do |t|
|
5
|
+
t.cucumber_opts = ['--format', 'pretty', '--require', 'features']
|
6
|
+
end
|
7
|
+
|
8
|
+
desc "setup a rails app for running cucumber"
|
9
|
+
file "cucumber_test_app" do
|
10
|
+
puts "** setting up cucumber test app ** (rails 2.3 only at present)"
|
11
|
+
Rake::Task['cucumber:setup'].invoke
|
12
|
+
end
|
13
|
+
|
14
|
+
namespace :cucumber do
|
15
|
+
task :setup do
|
16
|
+
rm_rf "cucumber_test_app"
|
17
|
+
sh "rails cucumber_test_app"
|
18
|
+
cd "cucumber_test_app" do
|
19
|
+
sh "script/generate rspec"
|
20
|
+
sh "script/generate cucumber"
|
21
|
+
end
|
22
|
+
sh "ln -s #{File.expand_path('.')} cucumber_test_app/vendor/plugins/pickle"
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'jeweler'
|
2
|
+
require 'pickle/version'
|
3
|
+
|
4
|
+
Jeweler::Tasks.new do |s|
|
5
|
+
s.name = "pickle"
|
6
|
+
s.version = Pickle::Version::String
|
7
|
+
s.summary = "Easy model creation and reference in your cucumber features"
|
8
|
+
s.description = "Easy model creation and reference in your cucumber features"
|
9
|
+
s.email = "ian.w.white@gmail.com"
|
10
|
+
s.homepage = "http://github.com/ianwhite/pickle/tree"
|
11
|
+
s.authors = ["Ian White"]
|
12
|
+
s.add_dependency('rspec', ">=1.3")
|
13
|
+
s.add_dependency('cucumber', ">=0.8")
|
14
|
+
s.add_dependency('yard')
|
15
|
+
s.add_dependency('rake')
|
16
|
+
end
|
17
|
+
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
|
20
|
+
namespace :release do
|
21
|
+
desc "release to github and gemcutter"
|
22
|
+
task :all => ['release', 'gemcutter:release']
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec/rake/spectask'
|
2
|
+
require 'spec/rake/verify_rcov'
|
3
|
+
|
4
|
+
desc "Generate RCov report"
|
5
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
6
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
7
|
+
t.rcov = true
|
8
|
+
t.rcov_dir = 'doc/coverage'
|
9
|
+
t.rcov_opts = ['--text-report', '--exclude', "gems/,features/,/Library,spec/,rcov.rb"]
|
10
|
+
end
|
11
|
+
|
12
|
+
namespace :rcov do
|
13
|
+
desc "Verify RCov threshold"
|
14
|
+
RCov::VerifyTask.new(:verify => :rcov) do |t|
|
15
|
+
t.threshold = 98.12
|
16
|
+
t.index_html = 'doc/coverage/index.html'
|
17
|
+
end
|
18
|
+
end
|
data/Todo.txt
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.2
|
data/features/app/app.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# Routes
|
2
|
+
ActionController::Routing::Routes.draw do |map|
|
3
|
+
map.resources :spoons, :controller => 'default'
|
4
|
+
map.resources :forks, :controller => 'default' do |fork|
|
5
|
+
fork.resources :tines, :controller => 'default' do |tine|
|
6
|
+
tine.resources :comments, :controller => 'default'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
map.resources :users, :controller => 'default'
|
10
|
+
end
|
11
|
+
|
12
|
+
# Migrations
|
13
|
+
ActiveRecord::Migration.suppress_messages do
|
14
|
+
ActiveRecord::Schema.define(:version => 0) do
|
15
|
+
create_table :forks, :force => true do |t|
|
16
|
+
t.string :name
|
17
|
+
end
|
18
|
+
|
19
|
+
create_table :spoons, :force => true do |t|
|
20
|
+
t.string :name
|
21
|
+
t.boolean :round, :default => true, :null => false
|
22
|
+
end
|
23
|
+
|
24
|
+
create_table :tines, :force => true do |t|
|
25
|
+
t.belongs_to :fork
|
26
|
+
t.boolean :rusty, :default => false, :null => false
|
27
|
+
end
|
28
|
+
|
29
|
+
create_table :users, :force => true do |t|
|
30
|
+
t.string :name, :status, :email
|
31
|
+
t.decimal :attitude_score, :precision => 4, :scale => 2
|
32
|
+
t.boolean :has_stale_password, :default => false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# Factories for these Fork & Spoon
|
39
|
+
class Fork < ActiveRecord::Base
|
40
|
+
validates_presence_of :name
|
41
|
+
has_many :tines
|
42
|
+
|
43
|
+
def completely_rusty?
|
44
|
+
tines.map(&:rusty?).uniq == [true]
|
45
|
+
end
|
46
|
+
|
47
|
+
def fancy?
|
48
|
+
name =~ /fancy/i
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Tine < ActiveRecord::Base
|
53
|
+
validates_presence_of :fork
|
54
|
+
belongs_to :fork
|
55
|
+
end
|
56
|
+
|
57
|
+
# Machinist blueprint for this
|
58
|
+
class Spoon < ActiveRecord::Base
|
59
|
+
validates_presence_of :name
|
60
|
+
end
|
61
|
+
|
62
|
+
# we don't want abstract classes getting in there
|
63
|
+
class AbstractUser < ActiveRecord::Base
|
64
|
+
self.abstract_class = true
|
65
|
+
end
|
66
|
+
|
67
|
+
# No factory or blueprint for this
|
68
|
+
class User < AbstractUser
|
69
|
+
validates_presence_of :name
|
70
|
+
|
71
|
+
def positive_person?
|
72
|
+
!no_attitude? && attitude_score > 0
|
73
|
+
end
|
74
|
+
|
75
|
+
def no_attitude?
|
76
|
+
attitude_score.nil?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# controllers
|
81
|
+
class DefaultController < ActionController::Base
|
82
|
+
def index
|
83
|
+
render :text => "index: I was invoked with #{request.path}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def show
|
87
|
+
render :text => "show: I was invoked with #{request.path}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def new
|
91
|
+
render :text => "new: I was invoked with #{request.path}"
|
92
|
+
end
|
93
|
+
|
94
|
+
def edit
|
95
|
+
render :text => "edit: I was invoked with #{request.path}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# notifiers
|
100
|
+
class Notifier < ActionMailer::Base
|
101
|
+
include ActionController::UrlWriter
|
102
|
+
|
103
|
+
# BC 2.1
|
104
|
+
if respond_to?(:view_paths)
|
105
|
+
view_paths << "#{File.dirname(__FILE__)}/views"
|
106
|
+
else
|
107
|
+
self.template_root = "#{File.dirname(__FILE__)}/views"
|
108
|
+
end
|
109
|
+
|
110
|
+
def user_email(user)
|
111
|
+
@recipients = user.email
|
112
|
+
@subject = 'A user email'
|
113
|
+
@body[:user] = user
|
114
|
+
@body[:path] = user_path(user)
|
115
|
+
end
|
116
|
+
|
117
|
+
def email(to, subject, body)
|
118
|
+
@recipients = to
|
119
|
+
@subject = subject
|
120
|
+
@body[:body] = body
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Factories
|
2
|
+
require 'factory_girl'
|
3
|
+
|
4
|
+
Factory.sequence :fork_name do |n|
|
5
|
+
"fork %d04" % n
|
6
|
+
end
|
7
|
+
|
8
|
+
Factory.define :fork do |f|
|
9
|
+
f.name { Factory.next(:fork_name) }
|
10
|
+
end
|
11
|
+
|
12
|
+
Factory.define :tine do |t|
|
13
|
+
t.association :fork
|
14
|
+
end
|
15
|
+
|
16
|
+
Factory.define :rusty_tine, :class => Tine do |t|
|
17
|
+
t.association :fork
|
18
|
+
t.rusty true
|
19
|
+
end
|
20
|
+
|
21
|
+
Factory.define :fancy_fork, :class => Fork do |t|
|
22
|
+
t.name { "Fancy " + Factory.next(:fork_name) }
|
23
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= @body %>
|