judit-pickle 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +20 -0
  3. data/Gemfile.lock +98 -0
  4. data/History.txt +409 -0
  5. data/License.txt +20 -0
  6. data/README.rdoc +367 -0
  7. data/Rakefile +20 -0
  8. data/Rakefile.d/cucumber.rake +24 -0
  9. data/Rakefile.d/jeweler.rake +23 -0
  10. data/Rakefile.d/rcov.rake +18 -0
  11. data/Rakefile.d/rspec.rake +7 -0
  12. data/Rakefile.d/yard.rake +5 -0
  13. data/Todo.txt +3 -0
  14. data/VERSION +1 -0
  15. data/features/app/app.rb +122 -0
  16. data/features/app/blueprints.rb +11 -0
  17. data/features/app/factories.rb +23 -0
  18. data/features/app/views/notifier/email.erb +1 -0
  19. data/features/app/views/notifier/user_email.erb +6 -0
  20. data/features/email/email.feature +64 -0
  21. data/features/generator/generators.feature +59 -0
  22. data/features/path/models_page.feature +44 -0
  23. data/features/path/named_route_page.feature +10 -0
  24. data/features/pickle/create_from_active_record.feature +76 -0
  25. data/features/pickle/create_from_factory_girl.feature +63 -0
  26. data/features/pickle/create_from_machinist.feature +39 -0
  27. data/features/step_definitions/email_steps.rb +63 -0
  28. data/features/step_definitions/extra_email_steps.rb +7 -0
  29. data/features/step_definitions/fork_steps.rb +4 -0
  30. data/features/step_definitions/generator_steps.rb +46 -0
  31. data/features/step_definitions/path_steps.rb +14 -0
  32. data/features/step_definitions/pickle_steps.rb +100 -0
  33. data/features/step_definitions/raise_error_steps.rb +3 -0
  34. data/features/support/email.rb +21 -0
  35. data/features/support/env.rb +52 -0
  36. data/features/support/paths.rb +47 -0
  37. data/features/support/pickle.rb +26 -0
  38. data/features/support/pickle_app.rb +4 -0
  39. data/init.rb +0 -0
  40. data/lib/generators/pickle_generator.rb +69 -0
  41. data/lib/pickle/adapter.rb +137 -0
  42. data/lib/pickle/adapters/active_record.rb +57 -0
  43. data/lib/pickle/adapters/data_mapper.rb +42 -0
  44. data/lib/pickle/adapters/mongoid.rb +44 -0
  45. data/lib/pickle/config.rb +49 -0
  46. data/lib/pickle/email/parser.rb +18 -0
  47. data/lib/pickle/email/world.rb +13 -0
  48. data/lib/pickle/email.rb +77 -0
  49. data/lib/pickle/parser/matchers.rb +87 -0
  50. data/lib/pickle/parser.rb +65 -0
  51. data/lib/pickle/path/world.rb +5 -0
  52. data/lib/pickle/path.rb +45 -0
  53. data/lib/pickle/session/parser.rb +34 -0
  54. data/lib/pickle/session.rb +205 -0
  55. data/lib/pickle/version.rb +9 -0
  56. data/lib/pickle/world.rb +14 -0
  57. data/lib/pickle.rb +26 -0
  58. data/pickle.gemspec +134 -0
  59. data/rails_generators/pickle/pickle_generator.rb +33 -0
  60. data/rails_generators/pickle/templates/email.rb +21 -0
  61. data/rails_generators/pickle/templates/email_steps.rb +63 -0
  62. data/rails_generators/pickle/templates/paths.rb +47 -0
  63. data/rails_generators/pickle/templates/pickle.rb +28 -0
  64. data/rails_generators/pickle/templates/pickle_steps.rb +100 -0
  65. data/spec/pickle/adapter_spec.rb +186 -0
  66. data/spec/pickle/config_spec.rb +109 -0
  67. data/spec/pickle/email/parser_spec.rb +51 -0
  68. data/spec/pickle/email_spec.rb +166 -0
  69. data/spec/pickle/parser/matchers_spec.rb +70 -0
  70. data/spec/pickle/parser_spec.rb +161 -0
  71. data/spec/pickle/path_spec.rb +101 -0
  72. data/spec/pickle/session_spec.rb +434 -0
  73. data/spec/pickle_spec.rb +24 -0
  74. data/spec/spec_helper.rb +8 -0
  75. 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
@@ -0,0 +1,7 @@
1
+ require 'spec/rake/spectask'
2
+
3
+ desc "Run the specs"
4
+ Spec::Rake::SpecTask.new(:spec) do |t|
5
+ t.spec_files = FileList['spec/**/*_spec.rb']
6
+ t.spec_opts = ["--colour"]
7
+ end
@@ -0,0 +1,5 @@
1
+ require 'yard'
2
+
3
+ YARD::Rake::YardocTask.new(:doc) do |t|
4
+ t.files = ['lib/**/*.rb', 'rails_generators/**/*.rb']
5
+ end
data/Todo.txt ADDED
@@ -0,0 +1,3 @@
1
+ * add 'scope' steps see http://gist.github.com/239570
2
+ * cleanup path_to_pickle and paths.rb (maybe have poly_pickle_path with same semantics as polymorphic_path, but accepting pickle refs)
3
+ * Translations
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.2
@@ -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,11 @@
1
+ # Blueprints
2
+ require 'machinist/active_record'
3
+
4
+ Sham.spoon_name { |i| "Spoon #{i}" }
5
+
6
+ Spoon.blueprint do
7
+ name { Sham.spoon_name }
8
+ end
9
+
10
+ # reset shams between scenarios
11
+ Before { Sham.reset }
@@ -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 %>
@@ -0,0 +1,6 @@
1
+ Dear <%= @user.name %>,
2
+
3
+ This is where you should go: <%= @path %>
4
+
5
+ Cheers,
6
+ The Pickle Team