wizardly_gt 0.1.8.9

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.
Files changed (37) hide show
  1. data/CHANGELOG.rdoc +33 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +656 -0
  4. data/init.rb +1 -0
  5. data/lib/jeffp-wizardly.rb +1 -0
  6. data/lib/validation_group.rb +150 -0
  7. data/lib/wizardly.rb +31 -0
  8. data/lib/wizardly/action_controller.rb +36 -0
  9. data/lib/wizardly/wizard.rb +16 -0
  10. data/lib/wizardly/wizard/button.rb +35 -0
  11. data/lib/wizardly/wizard/configuration.rb +194 -0
  12. data/lib/wizardly/wizard/configuration/methods.rb +422 -0
  13. data/lib/wizardly/wizard/dsl.rb +27 -0
  14. data/lib/wizardly/wizard/page.rb +62 -0
  15. data/lib/wizardly/wizard/text_helpers.rb +16 -0
  16. data/lib/wizardly/wizard/utils.rb +11 -0
  17. data/rails_generators/wizardly_app/USAGE +6 -0
  18. data/rails_generators/wizardly_app/templates/wizardly.rake +37 -0
  19. data/rails_generators/wizardly_app/wizardly_app_generator.rb +41 -0
  20. data/rails_generators/wizardly_controller/USAGE +3 -0
  21. data/rails_generators/wizardly_controller/templates/controller.rb.erb +34 -0
  22. data/rails_generators/wizardly_controller/templates/helper.rb.erb +14 -0
  23. data/rails_generators/wizardly_controller/wizardly_controller_generator.rb +57 -0
  24. data/rails_generators/wizardly_scaffold/USAGE +4 -0
  25. data/rails_generators/wizardly_scaffold/templates/form.html.erb +23 -0
  26. data/rails_generators/wizardly_scaffold/templates/form.html.haml.erb +22 -0
  27. data/rails_generators/wizardly_scaffold/templates/helper.rb.erb +30 -0
  28. data/rails_generators/wizardly_scaffold/templates/images/back.png +0 -0
  29. data/rails_generators/wizardly_scaffold/templates/images/cancel.png +0 -0
  30. data/rails_generators/wizardly_scaffold/templates/images/finish.png +0 -0
  31. data/rails_generators/wizardly_scaffold/templates/images/next.png +0 -0
  32. data/rails_generators/wizardly_scaffold/templates/images/skip.png +0 -0
  33. data/rails_generators/wizardly_scaffold/templates/layout.html.erb +15 -0
  34. data/rails_generators/wizardly_scaffold/templates/layout.html.haml.erb +10 -0
  35. data/rails_generators/wizardly_scaffold/templates/style.css +54 -0
  36. data/rails_generators/wizardly_scaffold/wizardly_scaffold_generator.rb +109 -0
  37. metadata +91 -0
@@ -0,0 +1,33 @@
1
+ == master
2
+
3
+ == 0.0.1 / 2009-07-28
4
+
5
+ * Created wizard implementation for submit_tag buttons
6
+ * Created WizardConfig, WizardPage and WizardButton
7
+ * Added wizard functions to validation_group (by alex kira)
8
+ * Created validation_group gem
9
+ * Added Implementation, Macro, Generated Controllers
10
+ * Refactored spec integration tests for the three controllers
11
+ * Created Wizardized_controller generator
12
+
13
+ == 0.0.2 / 2009-07-29
14
+
15
+ * script/generate wizardly_scaffold controller_name
16
+
17
+ == 0.0.3 / 2009-07-30
18
+
19
+ * added render_wizard_page for respond_to handling
20
+ * added wizard button and page callbacks
21
+ * tests for callbacks
22
+
23
+ == 0.0.3 / 2009-08-01
24
+
25
+ * refactored into library
26
+ * integrated validation_groups until later
27
+ * renamed to act_wizardly_for
28
+
29
+ == 0.1.0 /2009-08-02
30
+
31
+ * README.rdoc initial version
32
+ * gem version 0.1.0
33
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006-2009 Jeff Patmon
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,656 @@
1
+ = wizardly_gt
2
+
3
+ +wizardly+ by Jeff Patmon creates a multi-step wizard for any ActiveRecord model in three steps.
4
+
5
+ I fixed an error with a deprecated item in #add_with_validation_group method. See the instructions in the original README below, except add the following line to your environment.rb:
6
+
7
+ config.gem 'wizardly_gt', :lib => 'wizardly'
8
+
9
+ Instead of:
10
+
11
+ config.gem 'wizardly'
12
+
13
+ == Resources
14
+
15
+ Source
16
+
17
+ * git://github.com/jeffp/wizardly.git
18
+
19
+ Install
20
+
21
+ * sudo gem install wizardly --source=http://http://gemcutter.org
22
+
23
+ Examples
24
+
25
+ * http://github.com/jeffp/wizardly-examples
26
+
27
+ == Contributions
28
+
29
+ Thanks for feedback from Roland Schulz, Steve Hoeksema, Morgan Christiansson, Jonathan Clarke, Nate Delage
30
+
31
+ == Description
32
+
33
+ +wizardly+ builds on Alex Kira's +validation_group+ plugin code to
34
+ DRY up the Rails MVC implementation of a wizard. In three easy steps, +wizardly+
35
+ produces the scaffolding and controller of a multi-step wizard.
36
+
37
+ Features include:
38
+ * Model-based Wizard Definition
39
+ * Wizard Controller Macros
40
+ * Wizard Scaffold Generators
41
+ * Sizard Form Helpers
42
+ * Configurable Buttons
43
+ * Callbacks
44
+ * Paperclip Support
45
+
46
+ == Example
47
+
48
+ Create a working controller wizard for any model in 3 steps. Here's how:
49
+
50
+ Step 1: Define validation groups for your model.
51
+
52
+ class User < ActiveRecord::Base
53
+ validation_group :step1, :fields=>[:first_name, :last_name]
54
+ validation_group :step2, :fields=>[:age, :gender]
55
+ ...
56
+ end
57
+
58
+ Step 2: Tell your controller to act 'wizardly'.
59
+
60
+ class SignupController < ApplicationController
61
+ act_wizardly_for :user
62
+ end
63
+
64
+ Step 3: Generate a 'wizardly' scaffold for your controller.
65
+
66
+ ./script/generate wizardly_scaffold signup
67
+
68
+ You are ready to go: start your servers.
69
+
70
+ General usage and configuration of wizardly follows. See the examples at
71
+
72
+ http://github.com/jeffp/wizardly-examples
73
+
74
+ == Setup
75
+
76
+ Put the following in your application's config block in config/environment.rb
77
+
78
+ config.gem 'wizardly'
79
+
80
+ The temporarily (or permanently depending on github's reinstatement of gems) resides at
81
+ gemcutter.org. Make sure you have added gemcutter.org to your gem sources
82
+
83
+ and run the install gems rake task on your application
84
+
85
+ rake gems:install
86
+
87
+ === Setup Recommendations
88
+
89
+ Wizardly uses sessions. It is recommended you use a session store other than the
90
+ default cookies store to eliminate the 4KB size restriction. To use the active
91
+ record store, add this line to your environment.rb
92
+
93
+ config.action_controller.session_store = :active_record_store
94
+
95
+ And set up the sessions table in the database
96
+
97
+ rake db:sessions:create
98
+ rake db:migrate
99
+
100
+ Use the MemCached session store for higher performance requirements.
101
+
102
+ == Inspecting A Wizard Controller
103
+
104
+ This is optional, but for any rails app, you can install wizardly rake tasks
105
+ by running
106
+
107
+ ./script/generate wizardly_app
108
+
109
+ Once installed, you can run the config rake task to inspect a wizardly controller
110
+
111
+ rake wizardly:config name=controller_name
112
+
113
+ The controller_name you give it must have a +act_wizardly_for+ declaration for
114
+ an existing active record model and database table. (Don't forget to migrate
115
+ your database) The rake task will display the wizard's buttons, pages and fields
116
+ along with other configuration information.
117
+
118
+ == The Basic Wizard
119
+
120
+ Wizardly creates a controller action for each validation group
121
+ in the model. Likewise, the wizardly scaffold generates a view named for each
122
+ corresponding action.
123
+
124
+ === Action Instance Variables
125
+
126
+ The actions automatically instantiate a few instance variables: @step, @wizard,
127
+ @title and @{model_name}. @step contains the symbol corresponding to
128
+ the action name and is used in the wizard view helpers. @wizard references
129
+ the wizard configuration object and is primarily used by the view helpers.
130
+ @title contains the string name of the action by default and is used in the scaffolding. Finally and
131
+ most importantly of all, the action instantiates an instance of the model. For
132
+ instance, if the model is :account_user for AccountUser class, the action instantiates
133
+ an @account_user instance.
134
+
135
+ === Flow
136
+
137
+ The page-to-page flow of the wizard is assumed to occur in the order that the
138
+ validation groups were declared in the model. A 'next' button progresses to the
139
+ next page in the order; a 'back' button progresses to the previous page in the order.
140
+ The first page in the order will have no 'back' button. The final page in the order
141
+ will no 'next' button, but instead have a 'finish' button which completes the wizard
142
+ by saving the model instance to the database. Every page will have a 'cancel' button.
143
+
144
+ === Automatic Page Progression Tracking
145
+
146
+ The default progression is linear, progressing from one page to the next in the defined
147
+ order. In the default case, the 'back' button simply jumps back to the previous page.
148
+ However, the developer can create more complex flows by jumping and skipping pages in
149
+ the action callback methods. Wizardly tracks the forward progression
150
+ through a wizard and back tracks accordingly for the 'back' button.
151
+
152
+ === Wizard Entrance Guarding
153
+
154
+ Since there is an assumed order for the wizard, entering the wizard at a later page
155
+ makes no sense. Wizardly, however, guards entry to the wizard. If the user has
156
+ never entered the wizard, then entry is always redirected to the first page. If the
157
+ user has partially completed the wizard and is allowed to re-enter the wizard to
158
+ complete it, wizardly only allows entry at or before the page previously completed.
159
+
160
+ The guarding feature can be disabled for testing or other purposes.
161
+
162
+ == Basic Usage
163
+
164
+ === Completing and Canceling
165
+
166
+ Once a user has entered a wizard, there are two ways they can leave, either by
167
+ completing or canceling the wizard. The redirects for these two cases need to
168
+ be defined. If neither are defined, then the HTTP_REFERER on first entry of the
169
+ wizard is used as the redirect for both cases.
170
+
171
+ The 3-step example given above is very simple. In fact, no redirects have been defined for
172
+ completing or canceling the wizard so the wizardly controller
173
+ will use the HTTP_REFERER for both cases. If there is no HTTP_REFERER, the controller
174
+ raises a RedirectNotDefined error. Let's remedy this problem by adding redirect options
175
+ to the macro.
176
+
177
+ class SignupController < ApplicationController
178
+ act_wizardly_for :user,
179
+ :completed=>'/main/finished',
180
+ :canceled=>{:controller=>:main, :action=>:canceled}
181
+ end
182
+
183
+ Now whether the user completes or cancels the wizard, the controller knows
184
+ how to redirect. If both canceling and completing the wizard redirect to the
185
+ same place, the following option takes care of both
186
+
187
+ class SignupController < ApplicationController
188
+ act_wizardly_for :user, :redirect=>'/main'
189
+ end
190
+
191
+ These redirects are static, and may not suffice for all cases. In the event
192
+ that the redirect needs to be determined at run-time, the developer can use a
193
+ number of page callback macros to intercede in the wizard logic and redirect
194
+ as needed on canceling or completion. See Callbacks below.
195
+
196
+ ==== Controller Options
197
+
198
+ Here's a list of options for the +act_wizardly_for+ controller macro
199
+
200
+ :completed => '/main/finished'
201
+ :canceled => {:controller=>'main', :action=>'canceled'}
202
+ :skip => true
203
+ :cancel => false
204
+ :guard => false
205
+ :mask_fields => [:password, :password_confirmation] (by default)
206
+ :persist_model => {:per_page|:once}
207
+ :form_data => {:session|:sandbox}
208
+
209
+ Setting the :skip option to +true+ tells the scaffold helpers to include a skip button on each page.
210
+ The :cancel option set to +false+ removes the 'cancel' button from the wizard views.
211
+ The :mask_fields options tells the scaffold generator which fields to generate as 'type=password' fields.
212
+ Remaining options are explained below.
213
+
214
+ ==== Preserving Form Field Data
215
+
216
+ The :form_data option controls how the form data is preserved when a user
217
+ leaves or navigates to a page outside of the wizard before completing the wizard.
218
+ The default setting, :session, maintains the form data until the wizard is complete regardless of
219
+ whether the user leaves the wizard and returns later. The form
220
+ data is preserved for the life of the session or until the user completes the wizard.
221
+
222
+ The other setting, :sandbox, clears the form data whenever
223
+ the user leaves the wizard before the wizard is complete. This includes pressing
224
+ a :cancel button, a hyperlink or plainly navigating somewhere else.
225
+ Upon returning to the wizard, the form is reset and the user starts fresh from the
226
+ first page.
227
+
228
+ The form data is always cleared once the user has completed the wizard and the
229
+ record has been committed.
230
+
231
+ ==== Guarding Wizard Entry
232
+
233
+ The :guard option controls how a user may enter the wizard. If set to true, the
234
+ default, the wizard is guarded from entry anywhere except the first page. The wizard
235
+ controller will automatically redirect to the first page. When set to false, entry
236
+ may occur at any point. This may be useful for testing purposes and instances where
237
+ the application needs to navigate away and return to the wizard.
238
+
239
+ The guarding behavior works a little differently depending on the :form_data setting.
240
+ When :form_data is set to :session (the default behavior), guarding only occurs
241
+ for the initial entry. Once a user has entered the form and started it, while
242
+ form data is being kept, the application may thereafter enter anywhere. On the
243
+ contrary, if :form_data is set to :sandbox, entry is always guarded, and once the user
244
+ leaves the wizard, entry may only occur at the initial page (as the form data has
245
+ been reset).
246
+
247
+ ==== Persisting The Model
248
+
249
+ The :persist_model option controls how the model is saved, either :once or :per_page.
250
+ The default setting :per_page, saves the model incrementally for each page that
251
+ validates according to its validation group. This setting may result in invalid and
252
+ incomplete records in the database.
253
+
254
+ This problem can be remedied by using the :once setting, in which case, form data is
255
+ kept in the session until the wizard is complete and then saved out to the database.
256
+
257
+ The :once option does not work in all cases, particularly for any attribute that
258
+ can not be marshalled and dumped in the session. In particular, this will not work
259
+ for forms with file uploads like any forms using Paperclip. When using Paperclip, use
260
+ the :per_page setting.
261
+
262
+
263
+ === Buttons
264
+
265
+ The wizardly controller defines five default button functions: next, back, skip,
266
+ cancel, and finish. All but :skip are used in the scaffolding by default. You
267
+ can add :skip functionality to all pages by adding an option to the macro
268
+
269
+ class SignupController < ApplicationController
270
+ act_wizardly_for :user, :redirect=>'/main', :skip=>true
271
+ end
272
+
273
+ You can create, customize and change buttons for any controller and any page.
274
+ See the Button Customization section.
275
+
276
+
277
+ === Callbacks
278
+
279
+ There are two kinds of callbacks -- general and action. Action callbacks occur
280
+ based on a controller action. General callbacks occur based on a general wizard event.
281
+
282
+ ==== Action Callback Macros
283
+
284
+ Action callback macros are available for injecting code and control into the wizard
285
+ logic for each page. For instance, say our model
286
+ declares the following validation group
287
+
288
+ validation_group :step4, :fields=>[:username, :password, :password_confirmation]
289
+
290
+ In the case that there's a validation error, we'd like to clear the password fields before re-rendering
291
+ when one of the fields is invalid. For this purpose, we can use the on_errors action callback macro.
292
+
293
+ class SignupController < ApplicationController
294
+ act_wizardly_for :user, :redirect=>'/main'
295
+
296
+ on_errors(:step4) do
297
+ @user[:password] = ''
298
+ @user[:password_confirmation] = ''
299
+ end
300
+ end
301
+
302
+ Here's the list of action callbacks macros that the developer can use for any action
303
+
304
+ on_back(:step) # called when the :back button is pressed
305
+ on_skip(:step) # called when the skip button is pressed
306
+ on_cancel(:step) # called when the :cancel button is pressed
307
+ on_next(:step) # called when the :next button is pressed for a valid form (post only)
308
+ on_finish(:step) # called when the :finish button is pressed for a valid form (post only)
309
+
310
+ on_post(:step) # called at the beginning of a POST request
311
+ on_get(:step) # called before rendering a GET request
312
+ on_errors(:step) # called before re-rendering the form after form invalidation (on a POST request)
313
+
314
+ The first five callbacks are related to the wizard buttons. Each
315
+ callback gives the developer a chance to intervene before the impending render or
316
+ redirect caused by a button click.
317
+
318
+ Each callback macro consists of a list of actions or the symbol :all as the argument
319
+ and a block defining the code. For example
320
+
321
+ on_post(:step1) do
322
+ ...
323
+ end
324
+ on_back(:step2, :step3, :step4) do
325
+ ...
326
+ end
327
+ on_get(:all) do
328
+ ...
329
+ end
330
+
331
+ Passing a non-existing action name raises a CallbackError.
332
+
333
+ The block in a callback is called in the controller context, thus giving it access to all
334
+ controller variables and methods including the model instance, controller methods
335
+ like +redirect_to+, and controller variables like params, request, response and session.
336
+ The model instance variable is available for all action callback macros.
337
+
338
+ ==== The Wizard's Action Request Cycle
339
+
340
+ The wizard page is first requested through a GET to an action. In this GET request,
341
+ the wizard action creates the instance variables @step, @title and @wizard, and
342
+ builds the model instance variable @{model_name}. Action callbacks may occur in the
343
+ following order.
344
+
345
+ #GET request callback order
346
+
347
+ on_back, on_skip, on_cancel
348
+ on_get
349
+ render_wizard_form
350
+
351
+ If the wizard detects that a back, skip or cancel button has been pressed, the
352
+ corresponding callback is called if implemented. If the developer does nothing
353
+ in the callbacks, default handlers will redirect accordingly and the on_get and
354
+ render_wizard_form callbacks will not be called (Note: render_wizard_form is a
355
+ general callback and is included for completeness) Once rendered, the page is
356
+ presented to the user with a selection of fields and
357
+ wizard buttons for posting the form.
358
+
359
+ When the form data is returned by a POST request, the action creates the instance
360
+ variables and builds the model instance using the form data. The on_post callback
361
+ is called at the beginning of the post, then the wizard checks for back, skip and
362
+ cancel buttons. If neither of those buttons were pressed, it proceeds to validate
363
+ the form, calling the on_errors callback if form validation fails, re-rendering and
364
+ sending the page with errors. If validation succeeds, the action determines whether
365
+ the POST request signifies a 'next' or a 'finish' request and calls the corresponding
366
+ callback if implemented. The callback order for a POST request is as indicated below.
367
+ (The on_completed callback is a general callback called once the wizard is completed and
368
+ the model has been committed to the database)
369
+
370
+ #POST request callback order
371
+
372
+ on_post
373
+ on_back, on_skip, on_cancel
374
+ on_errors
375
+ render_wizard_form # only if errors
376
+ on_next
377
+ on_finish
378
+ on_completed # only if completed
379
+
380
+ ==== Rendering with on_get and on_errors
381
+
382
+ The on_get and on_errors callbacks are called just before rendering the form. These
383
+ callbacks are a good place to declare extra variables needed to render the form.
384
+
385
+ on_get(:step2) do
386
+ setup_step2_form
387
+ end
388
+
389
+ on_errors(:step2) do
390
+ setup_step2_form
391
+ end
392
+
393
+ def setup_step2_form
394
+ @contact_options = [%w(phone 1), %w(email 2), %w(mail, 3)]
395
+ end
396
+
397
+ If you have a variable that goes in every page, render_wizard_form is called
398
+ for every page.
399
+
400
+ ==== Modifying form data with on_post
401
+
402
+ The on_post callback is the first callback in the chain of a POST request and
403
+ is a good place to modify form input such as adding capitalization to a form.
404
+ Modification should happen through the model instance variable and not the
405
+ controller's params variable.
406
+
407
+ Redirecting and rendering are not allowed in the on_post callback. Doing so will
408
+ raise an error.
409
+
410
+ ==== Modifying Flow with on_next
411
+
412
+ on_next is called when a form has posted validly and the wizard is ready to move
413
+ to the next page. This is a good opportunity to modify form flow for more complex
414
+ forms by redirecting and skipping pages. See the STI Model example in
415
+ http://github.com/jeffp/wizardly-examples for an example of a wizard with two paths
416
+ based on user input.
417
+
418
+ on_next(:step1) do
419
+ redirect_to(:action=>:step3) if @contributor.is_volunteer?
420
+ end
421
+ on_next(:step2) do
422
+ redirect_to(:action=>:step4)
423
+ end
424
+
425
+ In the above example, :step 3 is a page for a volunteer, and :step2 is a page for
426
+ a non-volunteer.
427
+
428
+ ==== Completing the wizard with on_next
429
+
430
+ Sometimes you may want to complete the wizard based on user input rather than a
431
+ 'finish' button. You can call the +complete_wizard+ method. See the completing
432
+ wizard programmatically example below.
433
+
434
+ ==== Final modifications with on_finish
435
+
436
+ on_finish callback is called when the user presses a 'finish' button and form
437
+ validation is successful (for the validation_group). on_finish is a good place
438
+ to make any final modifications before the model instance is committed to the
439
+ database.
440
+
441
+ Alternatively, if you want to stop the completion process, you can call the
442
+ +do_not_complete+ method in the on_finish callback.
443
+
444
+ === General Callback Macros
445
+
446
+ There are two general callback macros: render_wizard_form and on_completed. These
447
+ are not tied to any action or set of actions.
448
+
449
+ ==== render_wizard_form
450
+
451
+ For anyone needing to handle rendering in a special way, wizardly provides a render
452
+ call back for this.
453
+
454
+ class SignupController < ApplicationController
455
+ act_wizardly_for :user, :redirect=>'/main'
456
+
457
+ def render_wizard_form
458
+ respond_to do |format|
459
+ format.html
460
+ format.xml { render_xml(@step) }
461
+ end
462
+ end
463
+
464
+ def render_xml(step)
465
+ ...
466
+ end
467
+ end
468
+
469
+ ==== Dynamic redirecting with on_completed
470
+
471
+ The on_completed callback is called once the model instance has been committed to
472
+ the database. If you need any fields generated from committing the model, such
473
+ as an ID, to redirect on completion, the
474
+ on_completed callback is the place to do this.
475
+
476
+ on_completed do
477
+ redirect_to post_path(@post)
478
+ end
479
+
480
+ === Helper methods
481
+
482
+ Wizardly provides some helper methods which are useful in callbacks.
483
+
484
+ ==== Completing the Wizard Programmatically
485
+
486
+ Perhaps you want to complete a wizard based off of a test instead of a button
487
+ click. You can do this in your callbacks by calling the +complete_wizard+ method.
488
+
489
+ on_next(:step4) do
490
+ if (test_radio_button)
491
+ complete_wizard
492
+ end
493
+ end
494
+
495
+ Complete wizard will save the model and redirect to the :completed redirect setting.
496
+ You can change the redirect dynamically by passing it to the method.
497
+
498
+ complete_wizard(some_model_path)
499
+
500
+ ==== Rerendering from a callback
501
+
502
+ Sometimes it is useful to re-render the form and send the response to the user immediately.
503
+ Wizardly provides a +render_and_return+ method for this purpose. If a callback is
504
+ triggered from a POST request, and the callback needs to re-render, this is the method.
505
+
506
+ on_back(:step2) do
507
+ if (something_mandatory_not_selected)
508
+ flash[:notice] = 'Please make a selection before going back'
509
+ render_and_return
510
+ end
511
+ end
512
+
513
+ === Creating Scaffolds
514
+
515
+ Wizard scaffolds can be created for any wizardly controller (one using the acts_wizardly_for
516
+ macro).
517
+
518
+ ./script/generate wizardly_scaffold controller_name --haml
519
+
520
+ The wizardly_scaffold generator will create HTML view scaffolds by default. Append a
521
+ --haml option to create scaffolds in HAML.
522
+
523
+ Sometimes you have already edited views from a scaffold but want to regenerate the
524
+ scaffold because of changes to your model without overwriting the current views.
525
+ Use the --underscore option to create corresponding views with an underscore prefixing
526
+ each page.
527
+
528
+ ./script/generate wizardly_scaffold controller_name --underscore
529
+
530
+ You can create a scaffold using image_submit_tag by doing the following:
531
+
532
+ ./script/generate wizardly_scaffold controller_name --image_submit
533
+
534
+ Default button images are provided under the public/images/wizardly/ directory.
535
+
536
+ == Button Customization
537
+
538
+ The buttons used by the wizard and the view helpers can be customized as follows.
539
+
540
+ === Changing Names of Default Wizard Buttons
541
+
542
+ The wizard supports five default button actions-- :next, :back, :cancel, :skip and
543
+ :finish. The default names for the buttons are the corresponding capitalized
544
+ string -- 'Next', 'Back', 'Cancel', 'Skip' and 'Finish'.
545
+
546
+ The default button names can be customized in the +act_wizardly_for+ code block
547
+
548
+ class UserSignupController < ApplicationController
549
+ act_wizardly_for :user, :redirect=>'/main/index' do
550
+ change_button(:back).name_to('Previous Page')
551
+ change_button(:finish).name_to('Save and Return')
552
+ end
553
+ end
554
+
555
+ With the above code, the 'Back' button will now be named 'Previous Page' and the 'Finish'
556
+ button is renamed to the longer name 'Save and Return'.
557
+
558
+ Notice that symbols are used
559
+ to determine the default button, but the customized name is passed. A new symbol
560
+ representing the change is created for each change, hence, for our buttons above :back
561
+ is now referred to as :previous_page and :finish is now referred to as :save_and_return.
562
+
563
+ === Action Callbacks for Customized Buttons
564
+
565
+ Changing the name of a default button does not change the name of its callback macro.
566
+ For instance, the renamed :back and :finish buttons above (to 'Previous Page' and 'Save and Return', respectively)
567
+ still use the on_back() and on_finish() callback macros despite the name change.
568
+
569
+ Perhaps though you want to change the symbol used to represent the button for consistancy
570
+ across your MVC. You can use the :id option when renaming to do so.
571
+
572
+ class UserSignupController < ApplicationController
573
+ act_wizardly_for :user, :redirect=>'/main/index' do
574
+ change_button(:back).name_to('Previous Page', :id=>:previous_page)
575
+ change_button(:finish).name_to('Save and Return', :id=>save_and_return)
576
+ end
577
+ end
578
+
579
+ Coding the above causes the :back button's ID to be replaced with :previous_page and so forth
580
+ for the :finish button. Thereafter, each button is referred to with the new ID. For instance,
581
+ the corresponding callback macros would be
582
+
583
+ on_previous_page(:step3) do
584
+ ...
585
+ end
586
+ on_save_and_return(:step3) do
587
+ ...
588
+ end
589
+
590
+ === Creating New Buttons
591
+
592
+ Completely new buttons can be added to the wizard by passing a button name to the +create_button+ method
593
+ in the +act_wizardly_for+ code block
594
+
595
+ act_wizardly_for :user, :redirect=>'/main/index' do
596
+ change_button(:back).name_to('Previous Page')
597
+ change_button(:finish).name_to('Save and Return')
598
+ ...
599
+ create_button('Help')
600
+ end
601
+
602
+ This creates a new button names 'Help' represented by the :help symbol. Actions for this
603
+ button must be defined by the on_help() callback macros for each and every page.
604
+
605
+ on_help(:all) do
606
+ case @step
607
+ when :step1 then ...
608
+ when :step2 then ...
609
+ end
610
+ end
611
+
612
+ Sometimes you may want to use the default ID given to the button. You can specify the ID
613
+ with the :id option. This is particularly useful for international languages.
614
+
615
+ create_button('Helfen', :id=>:help)
616
+
617
+ Now the help button will be called 'Helfen' in German and will be represented by :help in the code.
618
+
619
+ === Setting Buttons for a Wizard Page
620
+
621
+ Any new button needs to be explicitly added to every page it will show up on. Each
622
+ pages button set can be set in the +act_wizardly_for+ code as follows
623
+
624
+ act_wizardly_for :user, :redirect=>'/main/index' do
625
+ change_button(:back).name_to('Previous Page')
626
+ change_button(:finish).name_to('Save and Return')
627
+ ...
628
+ create_button('Help')
629
+ ...
630
+ set_page(:step1).buttons_to :next, :cancel, :help
631
+ set_page(:step2).buttons_to :next, :previous_page, :cancel, :help
632
+ set_page(:step3).buttons_to :save_and_return, :previous_page, :cancel, :help
633
+ end
634
+
635
+ === Viewing the Configuration
636
+
637
+ Use the wizardly rake tools to view the configuration of any wizard changes you make.
638
+
639
+ ./script/generate wizardly_app # if not already called for the project
640
+ rake wizardly:config name=controller_name
641
+
642
+ See the section 'Inspecting a Wizard Controller' above.
643
+
644
+ == Testing
645
+
646
+ Testing uses RSpec and Webrat. Make sure you have the gems installed. Then
647
+ to test the development code run the following:
648
+
649
+ rake spec:all
650
+
651
+
652
+ == Dependencies
653
+
654
+ * validation_group is currently integrated (plugin not required)
655
+ * ActiveRecord
656
+ * ActionController