Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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