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