juice10-action_flow 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/.document +5 -0
  2. data/Gemfile +13 -0
  3. data/Gemfile.lock +20 -0
  4. data/LICENSE.txt +20 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +206 -0
  7. data/Rakefile +53 -0
  8. data/VERSION +1 -0
  9. data/action_flow.gemspec +149 -0
  10. data/init.rb +1 -0
  11. data/install.rb +1 -0
  12. data/lib/action_flow.rb +59 -0
  13. data/lib/action_flow/blank_slate.rb +33 -0
  14. data/lib/action_flow/expression.rb +135 -0
  15. data/lib/action_flow/filters.rb +25 -0
  16. data/lib/action_flow/flow.rb +54 -0
  17. data/lib/action_flow/flow/controller.rb +91 -0
  18. data/lib/action_flow/flow/state.rb +73 -0
  19. data/lib/action_flow/helpers.rb +15 -0
  20. data/lib/action_flow/variable.rb +14 -0
  21. data/test/helper.rb +18 -0
  22. data/test/test_action_flow.rb +7 -0
  23. data/test_app/.gitignore +4 -0
  24. data/test_app/Gemfile +34 -0
  25. data/test_app/Gemfile.lock +131 -0
  26. data/test_app/README +256 -0
  27. data/test_app/Rakefile +7 -0
  28. data/test_app/app/controllers/application_controller.rb +6 -0
  29. data/test_app/app/controllers/settings_controller.rb +33 -0
  30. data/test_app/app/helpers/application_helper.rb +4 -0
  31. data/test_app/app/views/layouts/application.html.erb +14 -0
  32. data/test_app/app/views/settings/_step.html.erb +22 -0
  33. data/test_app/app/views/settings/intro.html.erb +12 -0
  34. data/test_app/app/views/settings/outro.html.erb +8 -0
  35. data/test_app/config.ru +4 -0
  36. data/test_app/config/application.rb +42 -0
  37. data/test_app/config/boot.rb +6 -0
  38. data/test_app/config/cucumber.yml +8 -0
  39. data/test_app/config/database.yml +25 -0
  40. data/test_app/config/environment.rb +5 -0
  41. data/test_app/config/environments/cucumber.rb +35 -0
  42. data/test_app/config/environments/development.rb +26 -0
  43. data/test_app/config/environments/production.rb +49 -0
  44. data/test_app/config/environments/test.rb +35 -0
  45. data/test_app/config/initializers/backtrace_silencers.rb +7 -0
  46. data/test_app/config/initializers/inflections.rb +10 -0
  47. data/test_app/config/initializers/mime_types.rb +5 -0
  48. data/test_app/config/initializers/secret_token.rb +7 -0
  49. data/test_app/config/initializers/session_store.rb +8 -0
  50. data/test_app/config/locales/en.yml +5 -0
  51. data/test_app/config/routes.rb +58 -0
  52. data/test_app/db/schema.rb +15 -0
  53. data/test_app/db/seeds.rb +7 -0
  54. data/test_app/features/flow_management.feature +122 -0
  55. data/test_app/features/flow_with_array_alternatives.feature +13 -0
  56. data/test_app/features/flows_with_conditions.feature +60 -0
  57. data/test_app/features/mutual_exclusion.feature +39 -0
  58. data/test_app/features/step_definitions/flow_steps.rb +20 -0
  59. data/test_app/features/step_definitions/url_steps.rb +7 -0
  60. data/test_app/features/step_definitions/web_steps.rb +211 -0
  61. data/test_app/features/support/env.rb +39 -0
  62. data/test_app/features/support/hooks.rb +3 -0
  63. data/test_app/features/support/paths.rb +33 -0
  64. data/test_app/features/support/selectors.rb +39 -0
  65. data/test_app/lib/tasks/.gitkeep +0 -0
  66. data/test_app/lib/tasks/cucumber.rake +57 -0
  67. data/test_app/public/404.html +26 -0
  68. data/test_app/public/422.html +26 -0
  69. data/test_app/public/500.html +26 -0
  70. data/test_app/public/favicon.ico +0 -0
  71. data/test_app/public/images/rails.png +0 -0
  72. data/test_app/public/index.html +239 -0
  73. data/test_app/public/javascripts/application.js +2 -0
  74. data/test_app/public/javascripts/controls.js +965 -0
  75. data/test_app/public/javascripts/dragdrop.js +974 -0
  76. data/test_app/public/javascripts/effects.js +1123 -0
  77. data/test_app/public/javascripts/prototype.js +6001 -0
  78. data/test_app/public/javascripts/rails.js +191 -0
  79. data/test_app/public/robots.txt +5 -0
  80. data/test_app/public/stylesheets/.gitkeep +0 -0
  81. data/test_app/script/about +4 -0
  82. data/test_app/script/console +3 -0
  83. data/test_app/script/cucumber +10 -0
  84. data/test_app/script/dbconsole +3 -0
  85. data/test_app/script/destroy +3 -0
  86. data/test_app/script/generate +3 -0
  87. data/test_app/script/performance/benchmarker +3 -0
  88. data/test_app/script/performance/profiler +3 -0
  89. data/test_app/script/plugin +3 -0
  90. data/test_app/script/rails +6 -0
  91. data/test_app/script/runner +3 -0
  92. data/test_app/script/server +3 -0
  93. data/test_app/test/performance/browsing_test.rb +9 -0
  94. data/test_app/test/test_helper.rb +13 -0
  95. data/test_app/vendor/plugins/.gitkeep +0 -0
  96. data/test_app/vendor/plugins/action_flow/init.rb +2 -0
  97. data/uninstall.rb +1 -0
  98. metadata +224 -0
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,13 @@
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 "shoulda", ">= 0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.2"
12
+ gem "rcov", ">= 0"
13
+ end
@@ -0,0 +1,20 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.5.2)
6
+ bundler (~> 1.0.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ rake (0.8.7)
10
+ rcov (0.9.9)
11
+ shoulda (2.11.3)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ bundler (~> 1.0.0)
18
+ jeweler (~> 1.5.2)
19
+ rcov
20
+ shoulda
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Justin Halsall
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,20 @@
1
+ Copyright (c) 2009 James Coglan
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,206 @@
1
+ = ActionFlow
2
+
3
+ This Rails plugin provides a simple way to model multi-step processes
4
+ such as wizards, sign-up flows, checkout processes and the like. It allows
5
+ sequences to be easily composed and reordered, as well as letting you
6
+ alter the behaviour and appearance of pages based on which flow they
7
+ have been accessed through.
8
+
9
+ == Contributing to action_flow
10
+
11
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
12
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
13
+ * Fork the project
14
+ * Start a feature/bugfix branch
15
+ * Commit and push until you are happy with your contribution
16
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
17
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
18
+
19
+ == Installation
20
+
21
+ script/plugin install git://github.com/jcoglan/action_flow.git
22
+
23
+ class ApplicationController < ActionController::Base
24
+ include ActionFlow::Filters
25
+ end
26
+
27
+ module ApplicationHelper
28
+ include ActionFlow::Helpers
29
+ end
30
+
31
+
32
+ == Specifying flows
33
+
34
+ Setup is done using a +configure+ block which you can place anywhere
35
+ is your application, though I'd recomment <tt>config/environment.rb</tt>
36
+ or <tt>app/controllers/application.rb</tt>. The block is a list of flows,
37
+ where each flow has a name and a list of controller actions. For example
38
+ let's create a flow for importing contacts from Gmail. The flow allows
39
+ you to import contacts, invite people to your site, and add people as
40
+ friends.
41
+
42
+ ActionFlow.configure do
43
+ flow :import_contacts, contacts.import,
44
+ contacts.invite,
45
+ users.add_friends,
46
+ contacts.done
47
+ end
48
+
49
+ This tells +ActionFlow+ that the +import_contacts+ flow is the sequence
50
+ of actions <tt>ContactsController#import</tt>, <tt>ContactsController#invite</tt>,
51
+ <tt>UsersController#add_friends</tt> and <tt>ContactsController#done</tt>.
52
+ On each request, +ActionFlow+ will watch the user's session and monitor
53
+ which flows they are in and how far through each flow they've progressed.
54
+
55
+ (The request-matching expressions <tt>contacts.import</tt> etc use the
56
+ Consent request expression language. More information here:
57
+ http://github.com/jcoglan/consent)
58
+
59
+ A user is judged to have begun a flow when they hit the first action in
60
+ that flow. They exit the flow when they've hit every page in the flow
61
+ in sequence. Multiple flows may be in play at once, and requests that
62
+ don't match any of the current flows are simply ignored: they do not
63
+ cause a flow to exit.
64
+
65
+
66
+ == Using flows to drive your app
67
+
68
+ +ActionFlow+ provides a few methods to controllers and views handle sending
69
+ the user to the next step in the flow and detecting which flow they are in.
70
+
71
+ <b><tt>next_in_flow(name)</tt></b> returns a params hash for the next action
72
+ in the named flow, based on the user's session history. If +ActionFlow+
73
+ cannot figure out the next action automatically, this method returns +nil+.
74
+
75
+ In views it simply returns the params hash for making links:
76
+
77
+ <%= link_to "Skip this step", next_in_flow(:import_contacts) %>
78
+
79
+ <b><tt>in_flow?(name)</tt></b> returns +true+ iff the user is in the named
80
+ flow, allowing you to alter the behaviour of controllers or the appearance
81
+ of views based on which flow(s) the user is currently in. This is especially
82
+ useful when reusing flows through composition, as described below.
83
+
84
+
85
+ == Composing flows
86
+
87
+ Flows can be spliced together, allowing you to embed one sequence of actions
88
+ inside another. Say we have a sign-up flow and we want to embed our contact
89
+ importer from above within it.
90
+
91
+ ActionFlow.configure do
92
+ flow :import_contacts, contacts.import,
93
+ contacts.invite,
94
+ users.add_friends,
95
+ contacts.done
96
+
97
+ flow :signup, users.new,
98
+ post(users.create),
99
+ :import_contacts,
100
+ dashboard.show
101
+ end
102
+
103
+ The <tt>signup</tt> flow begins with a request to <tt>UsersController#new</tt>,
104
+ followed by a POST request to <tt>UsersController#create</tt>. The symbol
105
+ <tt>:import_contacts</tt> that follows tells +ActionFlow+ to direct users
106
+ to the start of the <tt>import_contacts</tt> flow after <tt>UsersController#create</tt>,
107
+ whose implementation might look like this:
108
+
109
+ class UsersController < ApplicationController
110
+ def create
111
+ @user = User.new(params[:user])
112
+ return redirect_to next_in_flow(:signup) if @user.save
113
+ end
114
+ end
115
+
116
+ If the new user is valid, we go to the next step, otherwise we fall through
117
+ and render <tt>views/users/create.html.erb</tt> for them to correct the
118
+ errors.
119
+
120
+ While in the <tt>import_contacts</tt> flow, +ActionFlow+ will keep track
121
+ of both flows that are in play, allowing the user to skip ahead within each
122
+ flow. In your views, you can make use of this as follows:
123
+
124
+ # Links to ContactsController#invite
125
+ <%= link_to "Skip", next_in_flow(:import_contacts) %>
126
+
127
+ # Links to DashboardController#show
128
+ <%= link_to "Skip", next_in_flow(:signup) %>
129
+
130
+
131
+ == Flow conditions
132
+
133
+ Flow conditions give you finer control over whether a request should progress
134
+ a flow. You can attach a block of arbitrary Ruby code to request expressions
135
+ to provide more matching control. For example you could only allow a certain
136
+ flow to be entered if the first request is not an Ajax request:
137
+
138
+ ActionFlow.configure do
139
+ flow :signup, users.new { not request.xhr? },
140
+ users.create,
141
+ users.message
142
+ end
143
+
144
+
145
+ == Mutually exclusive flows
146
+
147
+ Sometimes you want two more flows to be mutually exclusive, for example if
148
+ you're trying a few different orderings of a process in different parts of
149
+ your application. The +mutex+ command takes a list of flow names and makes
150
+ sure that only one flow in that list can be active at once.
151
+
152
+ ActionFlow.configure do
153
+ flow :signup, users.new,
154
+ users.create,
155
+ users.message
156
+
157
+ flow :alternate_signup, users.message,
158
+ users.new,
159
+ users.create
160
+
161
+ mutex :signup, :alternate_signup
162
+ end
163
+
164
+ This makes it easier to reason about which step ActionFlow will pick next
165
+ since you know only one of these flows will apply at any time.
166
+
167
+
168
+ == Flow variables
169
+
170
+ Each flow a user is in gets its own session-like variable store, which
171
+ allows data to be passed forward through a flow without having to
172
+ store them as passthrough parameters in URLs. For example, say that
173
+ I want to modify my app so that we go to <tt>/users/:username/profile</tt>
174
+ at the end of the <tt>signup</tt> flow. We don't know the value of
175
+ <tt>:username</tt> in advance, as it's determined during signup. But
176
+ we can get +ActionFlow+ to redirect to the correct place using the
177
+ +find+ wrapper within our config and storing the needed data in the
178
+ flow's "session".
179
+
180
+ ActionFlow.configure do
181
+ flow :signup, users.new,
182
+ post(users.create),
183
+ profiles.show(:user_id => find(:username))
184
+ end
185
+
186
+ class UsersController
187
+ def create
188
+ @user = User.new(params[:user])
189
+ if @user.save
190
+ flow[:username] = @user.username
191
+ redirect_to next_in_flow(:signup)
192
+ end
193
+ end
194
+ end
195
+
196
+ Setting <tt>flow[:username]</tt> gives +ActionFlow+ the information
197
+ it needs to fill in the details for the next request: assuming I
198
+ signed up with the username "jcoglan", here +next_in_flow+
199
+ redirects to <tt>{:controller => "profiles", :action => "show",
200
+ :user_id => "jcoglan"}</tt>.
201
+
202
+
203
+ == License
204
+
205
+ Copyright (c) 2009 James Coglan, released under the MIT license
206
+
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "juice10-action_flow"
16
+ gem.homepage = "http://github.com/juice10/action_flow"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{ActionFlow provides a simple way to model multi-step processes such as wizards, sign-up flows, checkout processes in Rails. }
19
+ gem.description = %Q{ActionFlow provides a simple way to model multi-step processes such as wizards, sign-up flows, checkout processes and the like in Rails. It allows sequences to be easily composed and reordered, as well as letting you alter the behaviour and appearance of pages based on which flow they have been accessed through.}
20
+ gem.email = "justin@juice10.com"
21
+ gem.authors = ["Justin Halsall"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rake/testtask'
30
+ Rake::TestTask.new(:test) do |test|
31
+ test.libs << 'lib' << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+
36
+ require 'rcov/rcovtask'
37
+ Rcov::RcovTask.new do |test|
38
+ test.libs << 'test'
39
+ test.pattern = 'test/**/test_*.rb'
40
+ test.verbose = true
41
+ end
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "action_flow #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,149 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{action_flow}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Justin Halsall"]
12
+ s.date = %q{2011-04-19}
13
+ s.description = %q{ActionFlow provides a simple way to model multi-step processes such as wizards, sign-up flows, checkout processes and the like in Rails. It allows sequences to be easily composed and reordered, as well as letting you alter the behaviour and appearance of pages based on which flow they have been accessed through.}
14
+ s.email = %q{justin@juice10.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "MIT-LICENSE",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "action_flow.gemspec",
29
+ "init.rb",
30
+ "install.rb",
31
+ "lib/action_flow.rb",
32
+ "lib/action_flow/blank_slate.rb",
33
+ "lib/action_flow/expression.rb",
34
+ "lib/action_flow/filters.rb",
35
+ "lib/action_flow/flow.rb",
36
+ "lib/action_flow/flow/controller.rb",
37
+ "lib/action_flow/flow/state.rb",
38
+ "lib/action_flow/helpers.rb",
39
+ "lib/action_flow/variable.rb",
40
+ "test/helper.rb",
41
+ "test/test_action_flow.rb",
42
+ "test_app/.gitignore",
43
+ "test_app/Gemfile",
44
+ "test_app/Gemfile.lock",
45
+ "test_app/README",
46
+ "test_app/Rakefile",
47
+ "test_app/app/controllers/application_controller.rb",
48
+ "test_app/app/controllers/settings_controller.rb",
49
+ "test_app/app/helpers/application_helper.rb",
50
+ "test_app/app/views/layouts/application.html.erb",
51
+ "test_app/app/views/settings/_step.html.erb",
52
+ "test_app/app/views/settings/intro.html.erb",
53
+ "test_app/app/views/settings/outro.html.erb",
54
+ "test_app/config.ru",
55
+ "test_app/config/application.rb",
56
+ "test_app/config/boot.rb",
57
+ "test_app/config/cucumber.yml",
58
+ "test_app/config/database.yml",
59
+ "test_app/config/environment.rb",
60
+ "test_app/config/environments/cucumber.rb",
61
+ "test_app/config/environments/development.rb",
62
+ "test_app/config/environments/production.rb",
63
+ "test_app/config/environments/test.rb",
64
+ "test_app/config/initializers/backtrace_silencers.rb",
65
+ "test_app/config/initializers/inflections.rb",
66
+ "test_app/config/initializers/mime_types.rb",
67
+ "test_app/config/initializers/secret_token.rb",
68
+ "test_app/config/initializers/session_store.rb",
69
+ "test_app/config/locales/en.yml",
70
+ "test_app/config/routes.rb",
71
+ "test_app/db/schema.rb",
72
+ "test_app/db/seeds.rb",
73
+ "test_app/features/flow_management.feature",
74
+ "test_app/features/flow_with_array_alternatives.feature",
75
+ "test_app/features/flows_with_conditions.feature",
76
+ "test_app/features/mutual_exclusion.feature",
77
+ "test_app/features/step_definitions/flow_steps.rb",
78
+ "test_app/features/step_definitions/url_steps.rb",
79
+ "test_app/features/step_definitions/web_steps.rb",
80
+ "test_app/features/support/env.rb",
81
+ "test_app/features/support/hooks.rb",
82
+ "test_app/features/support/paths.rb",
83
+ "test_app/features/support/selectors.rb",
84
+ "test_app/lib/tasks/.gitkeep",
85
+ "test_app/lib/tasks/cucumber.rake",
86
+ "test_app/public/404.html",
87
+ "test_app/public/422.html",
88
+ "test_app/public/500.html",
89
+ "test_app/public/favicon.ico",
90
+ "test_app/public/images/rails.png",
91
+ "test_app/public/index.html",
92
+ "test_app/public/javascripts/application.js",
93
+ "test_app/public/javascripts/controls.js",
94
+ "test_app/public/javascripts/dragdrop.js",
95
+ "test_app/public/javascripts/effects.js",
96
+ "test_app/public/javascripts/prototype.js",
97
+ "test_app/public/javascripts/rails.js",
98
+ "test_app/public/robots.txt",
99
+ "test_app/public/stylesheets/.gitkeep",
100
+ "test_app/script/about",
101
+ "test_app/script/console",
102
+ "test_app/script/cucumber",
103
+ "test_app/script/dbconsole",
104
+ "test_app/script/destroy",
105
+ "test_app/script/generate",
106
+ "test_app/script/performance/benchmarker",
107
+ "test_app/script/performance/profiler",
108
+ "test_app/script/plugin",
109
+ "test_app/script/rails",
110
+ "test_app/script/runner",
111
+ "test_app/script/server",
112
+ "test_app/test/performance/browsing_test.rb",
113
+ "test_app/test/test_helper.rb",
114
+ "test_app/vendor/plugins/.gitkeep",
115
+ "test_app/vendor/plugins/action_flow/init.rb",
116
+ "uninstall.rb"
117
+ ]
118
+ s.homepage = %q{http://github.com/juice10/action_flow}
119
+ s.licenses = ["MIT"]
120
+ s.require_paths = ["lib"]
121
+ s.rubygems_version = %q{1.5.2}
122
+ s.summary = %q{ActionFlow provides a simple way to model multi-step processes such as wizards, sign-up flows, checkout processes in Rails.}
123
+ s.test_files = [
124
+ "test/helper.rb",
125
+ "test/test_action_flow.rb"
126
+ ]
127
+
128
+ if s.respond_to? :specification_version then
129
+ s.specification_version = 3
130
+
131
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
132
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
133
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
134
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
135
+ s.add_development_dependency(%q<rcov>, [">= 0"])
136
+ else
137
+ s.add_dependency(%q<shoulda>, [">= 0"])
138
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
139
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
140
+ s.add_dependency(%q<rcov>, [">= 0"])
141
+ end
142
+ else
143
+ s.add_dependency(%q<shoulda>, [">= 0"])
144
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
145
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
146
+ s.add_dependency(%q<rcov>, [">= 0"])
147
+ end
148
+ end
149
+