mrflip-pickle 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,147 @@
1
+ == 0.1.13 - 16 June 2009
2
+
3
+ * 2 minor enhancements
4
+ * model! and created_model! raise an error if pickle name can't be found
5
+ * path_to_pickle uses the above to give back a better error message
6
+
7
+
8
+ == 0.1.12 - 7 Apr 2009
9
+
10
+ * 2 minor enhancements
11
+ * rationalised Rakefile
12
+ * update World extensions for latest cucumber changes
13
+
14
+
15
+ == 0.1.11 - 22 Feb 2009
16
+
17
+ * 2 minor enhancements
18
+ * Pickle now supports multiple machinist blueprints
19
+ * Fix confusing adapter/adaptor comment generator comment
20
+
21
+
22
+ == 0.1.10 - 13 Feb 2009
23
+
24
+ * 2 minor enhancements
25
+ * Made pickle paths generator compatible with latest cucumber
26
+ * Simplified and Rakefile, including auto push api docs to gh-pages on ci build
27
+
28
+
29
+ == 0.1.9 - 29 Jan 2009
30
+
31
+ * 1 minor enhancement
32
+ * Pickle::Adapter.model_classes excludes those without tables
33
+
34
+
35
+ == 0.1.8 - 29 Jan 2009
36
+
37
+ * API change
38
+ * pickle_path becomes path_to_pickle, to avoid named route clashes
39
+
40
+ * 2 minor enhancements
41
+ * Updated features for cucumber 0.2 compat
42
+ * Made paths allow for optional possesives
43
+
44
+
45
+ == 0,1,7
46
+
47
+ * 2 API changes
48
+ * script/generate pickle path[s] now amends the features/support/paths.rb file
49
+ instead of creating pge_to_path and path_steps.
50
+
51
+ * pickle_email_steps is renamed email_steps
52
+
53
+
54
+ == 0.1.6
55
+
56
+ * 1 API change
57
+ * to use pickle env.rb should contain "require 'pickle/world'". You should remove all trace of
58
+ pickle from features/support/env.rb and re run script/generate pickle
59
+
60
+ * 2 major enhancements
61
+
62
+ * generate email steps with `script/generate pickle email`
63
+ email steps allow you to do things like this:
64
+
65
+ Then 2 emails should be delivered
66
+ And the first email should be delivered to fred@gmail.com
67
+ And the 2nd email should be delivered to the user: "ethel"
68
+
69
+ Then 1 email should be delivered with subject: "Activate your account"
70
+ And the email should link to the user's page
71
+
72
+ take a look at features/step_definitions/pickle_email_steps.rb
73
+
74
+ * generate path steps with `script/generate pickle path`
75
+ path steps allow you to do things like this
76
+
77
+ When I go to the comment's page
78
+ Then I should be at the user's new comment page
79
+
80
+ take a look at features/step_definitions/pickle_path_steps.rb, and modify page_to_path to suit your needs
81
+
82
+ * 4 minor enhancements
83
+ * Improved documentation
84
+ * abstract models no longer kill pickle
85
+ * Actually test that the generators work
86
+ * Made Pickle::Session a plain ole mixin, as a separate class was unnecessary
87
+ * Pickle uses the cucumber World API
88
+
89
+
90
+ == 0.1.5
91
+
92
+ * API change
93
+ * CaptureModel, etc are now 'capture_model' methods
94
+
95
+ * 3 major enhancements
96
+ * Steps for asserting that <n> models exist, matching certain criteria
97
+ * Steps for asserting associations added to generated pickle steps
98
+ 'Then the user should be in the post's commenters'
99
+ 'Then the forum: "awesome" should be the 2nd post's forum'
100
+ * configuration can now occur any time before a step is defined, which makes
101
+ for much more intuitive env.rb
102
+
103
+ * 2 minor enhancement
104
+ * predicate matching is less prone to step conflicts because we preload a
105
+ big list of all the predicate and column methods
106
+ * field values now handle booleans and numerics
107
+
108
+
109
+ == 0.1.4
110
+
111
+ * 1 major enhancement
112
+ * You can create multiple models with ease, for eg.
113
+ 'Given 10 users exist with role: "admin"'
114
+
115
+ * 1 minor enhancement
116
+ * You can do Pickle.configure (just like Webrat.configure)
117
+
118
+
119
+ == 0.1.3 - Bugfix release
120
+
121
+ * 1 minor enhancement
122
+ * make generated steps compatible with Rails 2.1
123
+
124
+
125
+ == 0.1.2
126
+
127
+ * 2 major enhancements
128
+ * create your pickle steps with script/generate pickle
129
+ * Adapter based architecture, supports Machinist, FactoryGirl, and vanilla ActiveRecord
130
+
131
+ * 1 minor enhancement
132
+ * model_names now defaults to subclasses of AR::Base
133
+ * #original_model => #created_model
134
+
135
+
136
+ == 0.1.1
137
+
138
+ * 1 major enhancement:
139
+ * made pickle a github gem
140
+
141
+ * 1 minor enhancement:
142
+ * Added intentions for pickle in README.textile
143
+
144
+
145
+ == Prior to gems
146
+
147
+ * Initial release: everything is subject to sweeping change
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008-2009 Ian White - ian.w.white@gmail.com
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.
@@ -0,0 +1,202 @@
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 but it's not as cool.
5
+
6
+ References to the models are stored, not necessarily for the purpose of checking the db
7
+ (although you could use it for that), but for enabling easy reference to urls, and for
8
+ building complex givens which require a bunch of models collaborating
9
+
10
+ == CI
11
+
12
+ It's tested against all stable branches of 2.x rails, and edge, with the latest versions of rspec, cucumber, factory_girl, machinist.
13
+
14
+ == Install
15
+
16
+ Install pickle either as a rails plugin, or a gem
17
+
18
+ # plugin
19
+ script/plugin install git://github.com/ianwhite/pickle.git
20
+
21
+ # or, plugin as submodule
22
+ git submodule add git://github.com/ianwhite/pickle.git vendor/plugins/pickle
23
+
24
+ # or, gem
25
+ sudo gem install ianwhite-pickle
26
+
27
+ == Get Started
28
+
29
+ (you'd better install cucumber)
30
+
31
+ script/generate pickle [paths] [email]
32
+
33
+ Now have a look at <tt>features/step_definitions/pickle_steps.rb</tt>
34
+
35
+ If you want path steps and email steps then just add 'paths' and/or 'email'. The code/steps will be
36
+ written to <tt>features/env/paths.rb</tt> and
37
+ <tt>features/step_definitions/email_steps.rb</tt> respectively.
38
+
39
+ === Using with plain ole Active Record
40
+
41
+ If you have an AR called 'Post', with required fields 'title', and 'body', then you can now write
42
+ steps like this
43
+
44
+ Given a post exists with title: "My Post", body: "My body"
45
+
46
+ === Using with factory-girl or machinist
47
+
48
+ But you're using Machinist or FactoryGirl right?! To leverage all of the factories/blueprints
49
+ you've written, you can just do stuff like
50
+
51
+ Given a user exists
52
+ And another user exists with role: "admin"
53
+
54
+ # later
55
+ Then a user should exist with name: "Fred"
56
+ And that user should be activated # this uses rspec predicate matchers
57
+
58
+ ==== Machinst: require your blueprints and reset Shams
59
+
60
+ (The latest version of pickle supports {multiple blueprints}[http://github.com/notahat/machinist/commit/d6492e6927a8aa1819926e48b22377171fd20496], for
61
+ earlier versions of machinist use pickle <= 0.1.10)
62
+
63
+ In your <tt>features/support/env.rb</tt> add the following lines at the bottom
64
+
65
+ require "#{Rails.root}/spec/blueprints" # or wherever they live
66
+ Before { Sham.reset } # reset Shams in between scenarios
67
+
68
+ === Configuring Pickle
69
+
70
+ You can tell pickle to use another factory adapter (see Pickle::Adapter), or
71
+ create mappings from english expressions to pickle model names. You can also
72
+ override many of the options on the Pickle::Config object if you so choose
73
+
74
+ require 'pickle/world'
75
+
76
+ Pickle.configure do |config|
77
+ config.adapters = [:machinist, YourOwnAdapterClass]
78
+ config.map 'me', 'myself', 'my', 'I', :to => 'user: "me"'
79
+ end
80
+
81
+ == API
82
+
83
+ === Steps
84
+
85
+ When you run <tt>script/generate pickle</tt> you get the following steps
86
+
87
+ ==== Given steps
88
+
89
+ "Given <b>a model</b> exists", e.g.
90
+
91
+ Given a user exists
92
+ Given a user: "fred" exists
93
+ Given the user exists
94
+
95
+ "Given <b>a model</b> exists with <b>fields</b>", e.g.
96
+
97
+ Given a user exists with name: "Fred"
98
+ Given a user exists with name: "Fred", activated: false
99
+
100
+ You can refer to other models in the fields
101
+
102
+ Given a user exists
103
+ And a post exists with author: the user
104
+
105
+ Given a person: "fred" exists
106
+ And a person: "ethel" exists
107
+ And a fatherhood exists with parent: user "fred", child: user "ethel"
108
+
109
+ "Given <b>n</b> models exist", e.g.
110
+
111
+ Given 10 users exist
112
+
113
+ "Given <b>n</b> <b>models</b> exist with <b>fields</b>", examples:
114
+
115
+ Given 10 users exist with activated: false
116
+
117
+ ==== Then steps
118
+
119
+ ===== Asserting existence of models
120
+
121
+ "Then <b>a model</b> should exist", e.g.
122
+
123
+ Then a user should exist
124
+
125
+ "Then <b>a model</b> should exist with <b>fields</b>", e.g.
126
+
127
+ Then a user: "fred" should exist with name: "Fred" # we can label the found user for later use
128
+
129
+ You can use other models, booleans, numerics, and strings as fields
130
+
131
+ Then a person should exist with child: person "ethel"
132
+ Then a user should exist with activated: false
133
+ Then a user should exist with activated: true, email: "fred@gmail.com"
134
+
135
+ "Then <b>n</b> <b>models</b> should exist", e.g.
136
+
137
+ Then 10 events should exist
138
+
139
+ "Then <b>n</b> <b>models</b> should exist with <b>fields</b>", e.g.
140
+
141
+ Then 2 people should exist with father: person "fred"
142
+
143
+ ===== Asserting associations
144
+
145
+ One-to-one assocs: "Then <b>a model</b> should be <b>other model</b>'s <b>association</b>", e.g.
146
+
147
+ Then the person: "fred" should be person: "ethel"'s father
148
+
149
+ Many-to-one assocs: "Then <b>a model</b> should be [in|one of] <b>other model</b>'s <b>association</b>", e.g.
150
+
151
+ Then the person: "ethel" should be one of person: "fred"'s children
152
+ Then the comment should be in the post's comments
153
+
154
+ ===== Asserting predicate methods
155
+
156
+ "Then <b>a model</b> should [be|have] [a|an] <b>predicate</b>", e.g.
157
+
158
+ Then the user should have a status # => user.status?.should == true
159
+ Then the car: "batmobile" should be fast # => car.fast?.should == true
160
+
161
+ "Then <b>a model</b> should [be|have] [a|an] <b>predicate</b>", e.g.
162
+
163
+ Then person: "fred" should not be childless # => fred.childless?.should == false
164
+
165
+ === Regexps for use in your own steps
166
+
167
+ By default you get some regexps available in the main namespace for use
168
+ in creating your own steps: `capture_model`, `capture_fields`, and others (see lib/pickle.rb)
169
+
170
+ (You can use any of the regexps that Pickle uses by using the Pickle.parser namespace, see
171
+ Pickle::Parser::Matchers for the methods available)
172
+
173
+ *capture_model*
174
+
175
+ Given /^#{capture_model} exists$/ do |model_name|
176
+ model(model_name).should_not == nil
177
+ end
178
+
179
+ Then /^I should be at the (.*?) page$/ |page|
180
+ if page =~ /#{capture_model}'s/
181
+ url_for(model($1))
182
+ else
183
+ # ...
184
+ end
185
+ end
186
+
187
+ Then /^#{capture_model} should be one of #{capture_model}'s posts$/ do |post, forum|
188
+ model(forum).posts.should include(post)
189
+ end
190
+
191
+ *capture_fields*
192
+
193
+ This is useful for setting attributes, and knows about pickle model names so that you
194
+ can build up composite objects with ease
195
+
196
+ Given /^#{capture_model} exists with #{capture_fields}$/ do |model_name, fields|
197
+ create_model(model_name, fields)
198
+ end
199
+
200
+ # example of use
201
+ Given a user exists
202
+ And a post exists with author: the user # this step will assign the above user as :author on the post
@@ -0,0 +1,4 @@
1
+ * Add email_for (same concept as path_to)
2
+ * fix problem with save_and_open_emails
3
+ * Translations
4
+ * Investigate using Treetop for pre-parsing
@@ -0,0 +1,26 @@
1
+ require 'active_support'
2
+ require 'pickle/version'
3
+ require 'pickle/adapter'
4
+ require 'pickle/config'
5
+ require 'pickle/parser'
6
+ require 'pickle/session'
7
+ require 'pickle/session/parser'
8
+
9
+ # make the parser aware of models in the session (for fields refering to models)
10
+ Pickle::Parser.send :include, Pickle::Session::Parser
11
+
12
+ module Pickle
13
+ class << self
14
+ def config
15
+ @config ||= Config.new
16
+ end
17
+
18
+ def configure(&block)
19
+ config.configure(&block)
20
+ end
21
+
22
+ def parser(options = {})
23
+ @parser ||= Parser.new({:config => config}.merge(options))
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,87 @@
1
+ module Pickle
2
+ # Abstract Factory adapter class, if you have a factory type setup, you
3
+ # can easily create an adaptor to make it work with Pickle.
4
+ #
5
+ # The factory adaptor must have a #factories class method that returns
6
+ # its instances, and each instance must respond to:
7
+ #
8
+ # #name : identifies the factory by name (default is attr_reader)
9
+ # #klass : returns the associated model class for this factory (default is attr_reader)
10
+ # #create(attrs = {}) : returns a newly created object
11
+ class Adapter
12
+ attr_reader :name, :klass
13
+
14
+ def self.factories
15
+ raise NotImplementedError, "return an array of factory adapter objects"
16
+ end
17
+
18
+ def create(attrs = {})
19
+ raise NotImplementedError, "create and return an object with the given attributes"
20
+ end
21
+
22
+ cattr_writer :model_classes
23
+ self.model_classes = nil
24
+
25
+ def self.model_classes
26
+ # remove abstract, framework, and non-table classes
27
+ @@model_classes ||= ::ActiveRecord::Base.send(:subclasses).reject do |klass|
28
+ klass.abstract_class? || !klass.table_exists? ||
29
+ (defined?(CGI::Session::ActiveRecordStore::Session) && klass == CGI::Session::ActiveRecordStore::Session) ||
30
+ (defined?(::ActiveRecord::SessionStore::Session) && klass == ::ActiveRecord::SessionStore::Session)
31
+ end
32
+ end
33
+
34
+ # machinist adapter
35
+ class Machinist < Adapter
36
+ def self.factories
37
+ factories = []
38
+ model_classes.each do |klass|
39
+ if blueprints = klass.instance_variable_get('@blueprints')
40
+ blueprints.keys.each {|blueprint| factories << new(klass, blueprint)}
41
+ end
42
+ end
43
+ factories
44
+ end
45
+
46
+ def initialize(klass, blueprint)
47
+ @klass, @blueprint = klass, blueprint
48
+ @name = @klass.name.underscore.gsub('/','_')
49
+ @name = "#{@blueprint}_#{@name}" unless @blueprint == :master
50
+ end
51
+
52
+ def create(attrs = {})
53
+ @klass.send(:make, @blueprint, attrs)
54
+ end
55
+ end
56
+
57
+ # factory-girl adapter
58
+ class FactoryGirl < Adapter
59
+ def self.factories
60
+ (::Factory.factories.values rescue []).map {|factory| new(factory)}
61
+ end
62
+
63
+ def initialize(factory)
64
+ @klass, @name = factory.build_class, factory.factory_name.to_s
65
+ end
66
+
67
+ def create(attrs = {})
68
+ Factory.create(@name, attrs)
69
+ end
70
+ end
71
+
72
+ # fallback active record adapter
73
+ class ActiveRecord < Adapter
74
+ def self.factories
75
+ model_classes.map {|klass| new(klass) }
76
+ end
77
+
78
+ def initialize(klass)
79
+ @klass, @name = klass, klass.name.underscore.gsub('/','_')
80
+ end
81
+
82
+ def create(attrs = {})
83
+ @klass.send(:create!, attrs)
84
+ end
85
+ end
86
+ end
87
+ end