wicked-focused 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/.rvmrc +19 -0
  2. data/.travis.yml +4 -0
  3. data/CHANGELOG.md +3 -0
  4. data/Gemfile +22 -0
  5. data/Gemfile.lock +122 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +253 -0
  8. data/Rakefile +50 -0
  9. data/VERSION +1 -0
  10. data/lib/wicked/action.rb +64 -0
  11. data/lib/wicked/controller/concerns/path.rb +29 -0
  12. data/lib/wicked/controller/concerns/render_redirect.rb +49 -0
  13. data/lib/wicked/controller/concerns/steps.rb +87 -0
  14. data/lib/wicked/engine.rb +4 -0
  15. data/lib/wicked/macros.rb +23 -0
  16. data/lib/wicked/wizard.rb +26 -0
  17. data/lib/wicked-focused.rb +25 -0
  18. data/test/dummy/Rakefile +7 -0
  19. data/test/dummy/app/controllers/application_controller.rb +3 -0
  20. data/test/dummy/app/controllers/bar_controller.rb +18 -0
  21. data/test/dummy/app/controllers/foo_controller.rb +19 -0
  22. data/test/dummy/app/controllers/jump_controller.rb +26 -0
  23. data/test/dummy/app/controllers/steps_controller.rb +18 -0
  24. data/test/dummy/app/helpers/application_helper.rb +2 -0
  25. data/test/dummy/app/models/bar.rb +9 -0
  26. data/test/dummy/app/views/bar/first.html.erb +5 -0
  27. data/test/dummy/app/views/bar/last_step.html.erb +3 -0
  28. data/test/dummy/app/views/bar/second.html.erb +3 -0
  29. data/test/dummy/app/views/foo/first.html.erb +1 -0
  30. data/test/dummy/app/views/foo/last_step.html.erb +1 -0
  31. data/test/dummy/app/views/foo/second.html.erb +1 -0
  32. data/test/dummy/app/views/jump/first.html.erb +1 -0
  33. data/test/dummy/app/views/jump/last_step.html.erb +1 -0
  34. data/test/dummy/app/views/jump/second.html.erb +1 -0
  35. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  36. data/test/dummy/app/views/step_positions/_step_position.html.erb +9 -0
  37. data/test/dummy/app/views/step_positions/first.html.erb +1 -0
  38. data/test/dummy/app/views/step_positions/last_step.html.erb +1 -0
  39. data/test/dummy/app/views/step_positions/second.html.erb +1 -0
  40. data/test/dummy/config/application.rb +45 -0
  41. data/test/dummy/config/boot.rb +10 -0
  42. data/test/dummy/config/database.yml +22 -0
  43. data/test/dummy/config/environment.rb +5 -0
  44. data/test/dummy/config/environments/development.rb +26 -0
  45. data/test/dummy/config/environments/production.rb +49 -0
  46. data/test/dummy/config/environments/test.rb +35 -0
  47. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  48. data/test/dummy/config/initializers/inflections.rb +10 -0
  49. data/test/dummy/config/initializers/mime_types.rb +5 -0
  50. data/test/dummy/config/initializers/secret_token.rb +7 -0
  51. data/test/dummy/config/initializers/session_store.rb +8 -0
  52. data/test/dummy/config/initializers/wicked.rb +2 -0
  53. data/test/dummy/config/locales/en.yml +5 -0
  54. data/test/dummy/config/routes.rb +8 -0
  55. data/test/dummy/config.ru +4 -0
  56. data/test/dummy/public/404.html +26 -0
  57. data/test/dummy/public/422.html +26 -0
  58. data/test/dummy/public/500.html +26 -0
  59. data/test/dummy/public/favicon.ico +0 -0
  60. data/test/dummy/public/index.html +1 -0
  61. data/test/dummy/public/javascripts/application.js +2 -0
  62. data/test/dummy/public/javascripts/controls.js +965 -0
  63. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  64. data/test/dummy/public/javascripts/effects.js +1123 -0
  65. data/test/dummy/public/javascripts/prototype.js +6001 -0
  66. data/test/dummy/public/javascripts/rails.js +202 -0
  67. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  68. data/test/dummy/script/rails +6 -0
  69. data/test/integration/helpers_test.rb +40 -0
  70. data/test/integration/jump_test.rb +16 -0
  71. data/test/integration/navigation_test.rb +88 -0
  72. data/test/integration/steps_test.rb +32 -0
  73. data/test/support/integration_case.rb +5 -0
  74. data/test/test_helper.rb +30 -0
  75. data/test/wicked_test.rb +7 -0
  76. data/wicked-focused.gemspec +138 -0
  77. metadata +270 -0
data/.rvmrc ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ruby_string="ruby-1.9.3-p125"
4
+ gemset_name="wicked"
5
+
6
+ if rvm list strings | grep -q "${ruby_string}" ; then
7
+
8
+ rvm use "${ruby_string}@${gemset_name}" --create
9
+
10
+ # Complain if bundler isn't installed
11
+ if [[ -z "`gem which bundler 2>&1 | grep -v ERROR`" ]]; then
12
+ echo "You need bundler:"
13
+ echo ""
14
+ echo " gem install bundler"
15
+ echo ""
16
+ fi
17
+ else
18
+ echo "${ruby_string} was not found, please run 'rvm install ${ruby_string}' and then cd back into the project directory."
19
+ fi
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.3
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## 0.2.0 (08/06/2012)
2
+
3
+ @kristianmandrup: Redesigned for use with Focused Controller. All tests pass :)
data/Gemfile ADDED
@@ -0,0 +1,22 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "activesupport" , ">= 3.0.7"
4
+ gem "rails" , ">= 3.0.7"
5
+
6
+ # with Action macros
7
+ gem 'focused_controller', :git => 'git://github.com/kristianmandrup/focused_controller.git'
8
+
9
+
10
+ group :development, :test do
11
+ gem 'rake'
12
+ gem 'jeweler', "~> 1.8.4"
13
+ gem "rcov", ">= 0"
14
+ gem "capybara", ">= 1.0.0"
15
+ gem "sqlite3"
16
+ gem "launchy"
17
+ end
18
+
19
+
20
+ # To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+)
21
+ # gem 'ruby-debug'
22
+ # gem 'ruby-debug19'
data/Gemfile.lock ADDED
@@ -0,0 +1,122 @@
1
+ GIT
2
+ remote: git://github.com/kristianmandrup/focused_controller.git
3
+ revision: 729d753a62abf4eadcfd76123f643973392bec3a
4
+ specs:
5
+ focused_controller (0.1.0)
6
+ actionpack (~> 3.0)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ abstract (1.0.0)
12
+ actionmailer (3.0.11)
13
+ actionpack (= 3.0.11)
14
+ mail (~> 2.2.19)
15
+ actionpack (3.0.11)
16
+ activemodel (= 3.0.11)
17
+ activesupport (= 3.0.11)
18
+ builder (~> 2.1.2)
19
+ erubis (~> 2.6.6)
20
+ i18n (~> 0.5.0)
21
+ rack (~> 1.2.1)
22
+ rack-mount (~> 0.6.14)
23
+ rack-test (~> 0.5.7)
24
+ tzinfo (~> 0.3.23)
25
+ activemodel (3.0.11)
26
+ activesupport (= 3.0.11)
27
+ builder (~> 2.1.2)
28
+ i18n (~> 0.5.0)
29
+ activerecord (3.0.11)
30
+ activemodel (= 3.0.11)
31
+ activesupport (= 3.0.11)
32
+ arel (~> 2.0.10)
33
+ tzinfo (~> 0.3.23)
34
+ activeresource (3.0.11)
35
+ activemodel (= 3.0.11)
36
+ activesupport (= 3.0.11)
37
+ activesupport (3.0.11)
38
+ addressable (2.2.7)
39
+ arel (2.0.10)
40
+ builder (2.1.2)
41
+ capybara (1.1.2)
42
+ mime-types (>= 1.16)
43
+ nokogiri (>= 1.3.3)
44
+ rack (>= 1.0.0)
45
+ rack-test (>= 0.5.4)
46
+ selenium-webdriver (~> 2.0)
47
+ xpath (~> 0.1.4)
48
+ childprocess (0.2.4)
49
+ ffi (~> 1.0.6)
50
+ erubis (2.6.6)
51
+ abstract (>= 1.0.0)
52
+ ffi (1.0.11)
53
+ git (1.2.5)
54
+ i18n (0.5.0)
55
+ jeweler (1.8.4)
56
+ bundler (~> 1.0)
57
+ git (>= 1.2.5)
58
+ rake
59
+ rdoc
60
+ json (1.6.4)
61
+ launchy (2.0.5)
62
+ addressable (~> 2.2.6)
63
+ mail (2.2.19)
64
+ activesupport (>= 2.3.6)
65
+ i18n (>= 0.4.0)
66
+ mime-types (~> 1.16)
67
+ treetop (~> 1.4.8)
68
+ mime-types (1.17.2)
69
+ multi_json (1.0.4)
70
+ nokogiri (1.5.0)
71
+ polyglot (0.3.3)
72
+ rack (1.2.5)
73
+ rack-mount (0.6.14)
74
+ rack (>= 1.0.0)
75
+ rack-test (0.5.7)
76
+ rack (>= 1.0)
77
+ rails (3.0.11)
78
+ actionmailer (= 3.0.11)
79
+ actionpack (= 3.0.11)
80
+ activerecord (= 3.0.11)
81
+ activeresource (= 3.0.11)
82
+ activesupport (= 3.0.11)
83
+ bundler (~> 1.0)
84
+ railties (= 3.0.11)
85
+ railties (3.0.11)
86
+ actionpack (= 3.0.11)
87
+ activesupport (= 3.0.11)
88
+ rake (>= 0.8.7)
89
+ rdoc (~> 3.4)
90
+ thor (~> 0.14.4)
91
+ rake (0.9.2.2)
92
+ rcov (0.9.11)
93
+ rdoc (3.12)
94
+ json (~> 1.4)
95
+ rubyzip (0.9.5)
96
+ selenium-webdriver (2.15.0)
97
+ childprocess (>= 0.2.1)
98
+ ffi (~> 1.0.9)
99
+ multi_json (~> 1.0.4)
100
+ rubyzip
101
+ sqlite3 (1.3.5)
102
+ thor (0.14.6)
103
+ treetop (1.4.10)
104
+ polyglot
105
+ polyglot (>= 0.3.1)
106
+ tzinfo (0.3.33)
107
+ xpath (0.1.4)
108
+ nokogiri (~> 1.3)
109
+
110
+ PLATFORMS
111
+ ruby
112
+
113
+ DEPENDENCIES
114
+ activesupport (>= 3.0.7)
115
+ capybara (>= 1.0.0)
116
+ focused_controller!
117
+ jeweler (~> 1.8.4)
118
+ launchy
119
+ rails (>= 3.0.7)
120
+ rake
121
+ rcov
122
+ sqlite3
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011 YOURNAME
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.md ADDED
@@ -0,0 +1,253 @@
1
+ # Wicked Focused
2
+
3
+ This gem is [wicked](https://github.com/schneems/wicked) tweaked for use with [focused controller](https://github.com/jonleighton/focused_controller).
4
+
5
+ [![Build Status](https://secure.travis-ci.org/schneems/wicked.png)](http://travis-ci.org/schneems/wicked)
6
+
7
+ Use wicked to make your Rails controllers into step-by-step wizards. To see Wicked in action check out the example [Rails app](https://github.com/schneems/wicked_example) or [watch the screencast](http://schneems.com/post/18437886598/wizard-ify-your-rails-controllers-with-wicked).
8
+
9
+ ## Why
10
+
11
+ Many times I'm left wanting a RESTful way to display a step by step process that may or not be associated with a resource. Wicked gives the flexibility to do what I want while hiding all the really nasty stuff you shouldn't do in a controller to make this possible. At it's core Wicked is a RESTful(ish) state machine, but you don't need to know that, just use it.
12
+
13
+ ## Install
14
+
15
+ Add this to your Gemfile
16
+
17
+ ```ruby
18
+ gem 'wicked-focused'
19
+ ```
20
+
21
+ Then run `bundle install` and you're ready to start
22
+
23
+ ## Quicklinks
24
+
25
+ * Build an object step-by-step using [Partial Validation of Active Record Objects](https://github.com/schneems/wicked/wiki/Partial-Validation-of-Active-Record-Objects)
26
+ * [Show Current Wizard Progress to User](https://github.com/schneems/wicked/wiki/Show-Current-Wizard-Progress-to-User)
27
+ * [Example App](https://github.com/schneems/wicked_example)
28
+ * [Screencast](http://schneems.com/post/18437886598/wizard-ify-your-rails-controllers-with-wicked)
29
+ * [Watch Railscasts episode: #346 Wizard Forms with Wicked](http://railscasts.com/episodes/346-wizard-forms-with-wicked)
30
+
31
+ ## How
32
+
33
+ We are going to build an 'after signup' wizard. First create a controller:
34
+
35
+ ```
36
+ rails g controller after_signup
37
+ ```
38
+
39
+ Add Routes into `config/routes.rb`:
40
+
41
+ ```ruby
42
+ resources :after_signup
43
+ ```
44
+
45
+ Next include `Wicked::Wizard` in your controller
46
+
47
+ ```ruby
48
+
49
+ class AfterSignupController
50
+ # base Wizard Action class of Controller must be called 'Action'
51
+ # and must include of Wizard::Action
52
+ class Action < FocusedAction
53
+ include Wizard::Action
54
+
55
+ steps :confirm_password, :confirm_profile, :find_friends
56
+ end
57
+
58
+ # creates Focused Action :index
59
+ include Wicked::Wizard
60
+
61
+ ```
62
+
63
+ The wizard is set to call steps in order in the show action, you can specify custom logic in your show using a case statement like below. To send someone to the first step in this wizard we can direct them to `after_signup_path(:confirm_password)`.
64
+
65
+ ```ruby
66
+ class AfterSignupController
67
+ class Action < FocusedAction
68
+ include Wizard::Action
69
+
70
+ steps :confirm_password, :confirm_profile, :find_friends
71
+ end
72
+ include Wicked::Wizard
73
+
74
+ class Show < Action
75
+ def run
76
+ wizard_redirect and return if super()
77
+ @user = current_user
78
+ case step
79
+ when :find_friends
80
+ @friends = @user.find_friends
81
+ end
82
+ render_wizard
83
+ end
84
+ end
85
+ end
86
+ ```
87
+
88
+ **Note:** Wicked uses the `:id` parameter to control the flow of steps, if you need to have an id parameter, please use nested routes see [Partial Validation of Active Record Objects](https://github.com/schneems/wicked/wiki/Partial-Validation-of-Active-Record-Objects) for an example. It will need to be prefixed, for example a Product's `:id` would be `:product_id`
89
+
90
+ You'll need to call `render_wizard` at the end of your action to get the correct views to show up.
91
+
92
+ By default the wizard will render a view with the same name as the step. So for our controller `AfterSignupController` with a view path of `/views/after_signup/` if call the :confirm_password step, our wizard will render `/views/after_signup/confirm_password.html.erb`
93
+
94
+ Then in your view you can use the helpers to get to the next step.
95
+
96
+ ```ruby
97
+ <%= link_to 'skip', next_wizard_path %>
98
+ ```
99
+
100
+ You can manually specify which wizard action you want to link to by using the wizard_path helper.
101
+
102
+ ```ruby
103
+ <%= link_to 'skip', wizard_path(:find_friends) %>
104
+ ```
105
+
106
+ In addition to showing sequential views we can update elements in our controller.
107
+ Note: Here we demonstrate the use of wicked macros.
108
+
109
+ ```ruby
110
+ class AfterSignupController
111
+ use_wicked_macros
112
+
113
+ wicked_base_action do
114
+ steps :confirm_password, :confirm_profile, :find_friends
115
+ end
116
+
117
+ wizard_action :update do
118
+ wizard do
119
+ @user = current_user
120
+ case step
121
+ when :confirm_password
122
+ @user.update_attributes(params[:user])
123
+ end
124
+ sign_in(@user, :bypass => true) # needed for devise
125
+ render_wizard @user
126
+ end
127
+ end
128
+ end
129
+ ```
130
+
131
+ We're passing `render_wizard` our `@user` object here. If you pass an object into `render_wizard` it will show the next step if the object saves or re-render the previous view if it does not save.
132
+
133
+ To get to this update action, you simply need to submit a form that PUT's to the same url
134
+
135
+ ```ruby
136
+
137
+ <%= form_for @user, :url => wizard_path, :method => :put do |f| %>
138
+ <%= f.password_field :password %>
139
+ <%= f.password_field :password_confirmation %>
140
+
141
+ <%= f.submit "Change Password" %>
142
+ <% end %>
143
+
144
+ ```
145
+
146
+ We explicitly tell the form to PUT above. If you forget this, you will get a warning about the create action not existing, or no route found for POST. Don't forget this.
147
+
148
+ In the controller if you find that you want to skip a step, you can do it simply by calling `skip_step`
149
+
150
+ ```ruby
151
+
152
+ wizard_action :show do
153
+ wizard do
154
+ @user = current_user
155
+ case step
156
+ when :find_friends
157
+ if @user.has_facebook_access_token?
158
+ @friends = @user.find_friends
159
+ else
160
+ skip_step
161
+ end
162
+ end
163
+ render_wizard
164
+ end
165
+ end
166
+
167
+ ```
168
+
169
+ Now you've got a fully functioning AfterSignup controller! If you have questions or if you struggled with something, let me know on [twitter](http://twitter.com/schneems), and i'll try to make it better or make the docs better.
170
+
171
+ ## Quick Reference
172
+
173
+ *Macros*
174
+
175
+ `use_wicked_macros` enables use of the Wicked macros. Otherwise you must explicitly create equivalent classes and methods.
176
+
177
+ `wicked_base_action name, &block`
178
+
179
+ Created the Focused Controller action base class, from which any Wizard Action class will inherit from.
180
+
181
+ `wizard_action name, &block`
182
+
183
+ Creates a Focused Controller action class inheriting from the base action class of the controller. The block contains the class definition.
184
+
185
+ `wizard`
186
+
187
+ Creates a `#run` method as "required" by a Focused Controller action class. The run method generated calls super which calls `setup_wizard` and also auto-handles redirects.
188
+
189
+ *View/URL Helpers*
190
+
191
+ ```ruby
192
+
193
+ wizard_path # Grabs the current path in the wizard
194
+ wizard_path(:specific_step) # Url of the :specific_step
195
+ next_wizard_path # Url of the next step
196
+ previous_wizard_path # Url of the previous step
197
+
198
+ # These only work while in a Wizard, and are not absolute paths
199
+ # You can have multiple wizards in a project with multiple `wizard_path` calls
200
+ ```
201
+
202
+ *Controller Tidbits:*
203
+
204
+ ```ruby
205
+ steps :first, :second # Sets the order of steps
206
+ step # Gets symbol of current step
207
+ next_step # Gets symbol of next step
208
+ skip_step # Tells render_wizard to skip to the next logical step
209
+ render_wizard # Renders the current step
210
+ render_wizard(@user) # Shows next_step if @user.save, otherwise renders current step
211
+ ```
212
+
213
+ Finally:
214
+
215
+ Don't forget to create your named views
216
+
217
+ ```
218
+ app/
219
+ views/
220
+ controller_name/
221
+ first.html.erb
222
+ second.html.erb
223
+ # ...
224
+ ```
225
+
226
+ # Finish Wizard Path
227
+
228
+ You can specify the url that your user goes to by over-riding the `finish_wizard_path` in your wizard controller action.
229
+
230
+
231
+ ```
232
+ def finish_wizard_path
233
+ user_path(current_user)
234
+ end
235
+ ```
236
+
237
+ ### Testing with RSpec
238
+
239
+ ```ruby
240
+ # Test find_friends block of show action
241
+ get :show, :id => :find_friends
242
+
243
+ # Test find_friends block of update action
244
+ put :update, {'id' => 'find_friends', "user" => { "id" => @user.id.to_s }}
245
+ ```
246
+
247
+ ## About
248
+
249
+ Please poke around the source code, if you see easier ways to get a Rails controller do do what I want, let me know.
250
+
251
+ If you have a question file an issue or, find me on the Twitters [@schneems](http://twitter.com/schneems).
252
+
253
+ This project rocks and uses MIT-LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems'
3
+ require 'bundler'
4
+
5
+ begin
6
+ Bundler.setup(:default, :development, :test)
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
+
13
+ require 'rake'
14
+ require 'rdoc/task'
15
+
16
+ require 'rake/testtask'
17
+
18
+ Rake::TestTask.new(:test) do |t|
19
+ t.libs << 'lib'
20
+ t.libs << 'test'
21
+ t.pattern = 'test/**/*_test.rb'
22
+ t.verbose = false
23
+ end
24
+
25
+ task :default => :test
26
+
27
+ Rake::RDocTask.new(:rdoc) do |rdoc|
28
+ rdoc.rdoc_dir = 'rdoc'
29
+ rdoc.title = 'Wicked Focused'
30
+ rdoc.options << '--line-numbers' << '--inline-source'
31
+ rdoc.rdoc_files.include('README.rdoc')
32
+ rdoc.rdoc_files.include('lib/**/*.rb')
33
+ end
34
+
35
+
36
+ require 'jeweler'
37
+ Jeweler::Tasks.new do |gem|
38
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
39
+ gem.name = "wicked-focused"
40
+ gem.homepage = "http://github.com/schneems/wicked"
41
+ gem.license = "MIT"
42
+ gem.summary = %Q{Use Wicked to turn your Focused Controller into a wizard}
43
+ gem.description = %Q{Rails engine for producing Focused Controller based wizards}
44
+ gem.email = "kmandrup@gmail.com"
45
+ gem.authors = ["kristianmandrup", "schneems"]
46
+ # dependencies defined in Gemfile
47
+ end
48
+ Jeweler::RubygemsDotOrgTasks.new
49
+
50
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1,64 @@
1
+ module Wicked
2
+ module Action
3
+ extend ActiveSupport::Concern
4
+
5
+ # Include the modules!!
6
+ include Wicked::Controller::Concerns::Path
7
+ include Wicked::Controller::Concerns::RenderRedirect
8
+ include Wicked::Controller::Concerns::Steps
9
+
10
+ included do
11
+ # Give our Views helper methods!
12
+ helper_method :wizard_path, :next_wizard_path, :previous_wizard_path,
13
+ :step, :wizard_steps, :current_step?,
14
+ :past_step?, :future_step?, :previous_step?,
15
+ :next_step?
16
+ end
17
+
18
+ # any subclass (Action class) should call super!
19
+ def run
20
+ setup_wizard
21
+ end
22
+
23
+ module ClassMethods
24
+ def wizard &block
25
+ define_method :run do
26
+ wizard_redirect and return if super()
27
+ instance_eval &block
28
+ end
29
+ end
30
+ end
31
+
32
+ protected
33
+
34
+ def setup_wizard
35
+ @redirect_path = wizard_path(steps.first) if first_step? && !on_first_step?
36
+ @redirect_path = wizard_path(steps.last) if last_step? && !on_last_step?
37
+
38
+ @step = params[:id].try(:to_sym) || steps.first
39
+ @previous_step = previous_step(@step)
40
+ @next_step = next_step(@step)
41
+ @redirect_path
42
+ end
43
+
44
+ def wizard_redirect
45
+ redirect_to @redirect_path if @redirect_path
46
+ end
47
+
48
+ def on_first_step?
49
+ step == steps.first
50
+ end
51
+
52
+ def on_last_step?
53
+ step == steps.first
54
+ end
55
+
56
+ def first_step?
57
+ params[:id].try(:to_sym) == :wizard_first
58
+ end
59
+
60
+ def last_step?
61
+ params[:id].try(:to_sym) == :wizard_last
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,29 @@
1
+ module Wicked::Controller::Concerns::Path
2
+ extend ActiveSupport::Concern
3
+
4
+ def next_wizard_path(options = {})
5
+ wizard_path(@next_step, options)
6
+ end
7
+
8
+ def previous_wizard_path(options = {})
9
+ wizard_path(@previous_step, options)
10
+ end
11
+
12
+ def wicked_controller
13
+ self.class.name.sub(/::\w+$/, '')
14
+ end
15
+
16
+ def wicked_controller_name
17
+ wicked_controller.sub(/Controller$/, '').gsub('::', '_').underscore
18
+ end
19
+
20
+ def wicked_action
21
+ params[:action]
22
+ end
23
+
24
+ def wizard_path(goto_step = nil, options = {})
25
+ id = goto_step || params[:id]
26
+ path_method = "#{wicked_controller_name}_path"
27
+ send path_method, id, options
28
+ end
29
+ end
@@ -0,0 +1,49 @@
1
+ module Wicked::Controller::Concerns::RenderRedirect
2
+ extend ActiveSupport::Concern
3
+
4
+
5
+ def render_wizard(resource = nil, options = {})
6
+ process_resource!(resource)
7
+ if @skip_to
8
+ redirect_to wizard_path(@skip_to), options
9
+ else
10
+ render_step @step, options
11
+ end
12
+ end
13
+
14
+ def process_resource!(resource)
15
+ if resource
16
+ if resource.save
17
+ @skip_to ||= @next_step
18
+ else
19
+ @skip_to = nil
20
+ end
21
+ end
22
+ end
23
+
24
+ def render_step(the_step, options = {})
25
+ if the_step.nil? || the_step == :finish
26
+ redirect_to_finish_wizard options
27
+ else
28
+ render the_step, options
29
+ end
30
+ end
31
+
32
+ def redirect_to_next(next_step)
33
+ if next_step.nil?
34
+ redirect_to_finish_wizard
35
+ else
36
+ redirect_to wizard_path(next_step)
37
+ end
38
+ end
39
+
40
+ # TODO redirect to resource if one is passed to render_wizard
41
+ def finish_wizard_path
42
+ '/'
43
+ end
44
+
45
+ def redirect_to_finish_wizard(options = nil)
46
+ redirect_to finish_wizard_path, options
47
+ end
48
+
49
+ end