wizardly_gt 0.1.8.9

Sign up to get free protection for your applications and to get access to all the features.
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