jeffp-wizardly 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -146,37 +146,37 @@ See the Advanced Configuration section.
146
146
  === Callbacks
147
147
 
148
148
  The wizard macro 'act_wizardly_for' creates controller actions for each page.
149
- The process for each page is conventional, but hooks (or callbacks) are available
150
- for the developer to change the processing. Here's an example. Say our model
149
+ The processing is standard for a wizard. Hooks or callback macros are available
150
+ for changing or interrupting the processing. Here's an example. Say our model
151
151
  declares a :step4 validation_group with :username, :password, and
152
152
  :password_confirmation fields. We'd like to handle this step specifically.
153
153
 
154
154
  class SignupController < ApplicationController
155
155
  act_wizardly_for :user, :redirect=>'/main'
156
156
 
157
- def on_invalid_step4_form
157
+ on_errors(:step4) do
158
158
  #clear the password field if errors
159
159
  @user[:password] = ''
160
160
  @user[:password_confirmation] = ''
161
161
  end
162
162
  end
163
163
 
164
- The above callback is only called if :step4 does not validate according to its
164
+ The above hook macro is only called if :step4 does not validate according to its
165
165
  validation_group.
166
166
 
167
- Every page has a set of callbacks. Here's the list for our :step1 page.
167
+ Every page has a set of callback macros. Here's the list.
168
168
 
169
- def on_get_step1_form; end
170
- def on_post_step1_form; end
171
- def on_invalid_step1_form; end
172
- def on_step1_form_next; end
173
- def on_step1_form_back; end
174
- def on_step1_form_cancel; end
175
- def on_step1_form_finish; end
176
- def on_step1_form_skip; end
169
+ on_get(:step) # called just after creating model instance and before rendering a GET request
170
+ on_post(:step) # called just after creating the model instance for a POST request
171
+ on_errors(:step) # called after on_post callback if the form is invalid according to validation group
172
+ on_next(:step) # called on a valid form when :next button is pressed
173
+ on_back(:step) # called when the :back button is pressed
174
+ on_cancel(:step) # called when the :cancel button is pressed
175
+ on_finish(:step) # called on a valid form when the :finish button is pressed
176
+ on_skip(:step) # called when the skip button is pressed
177
177
 
178
- Each callback is defined for the controller object, thus giving it access to all
179
- controller variables and methods just as any other action method. Each callback
178
+ The block for each hook is called in the controller context, thus giving it access to all
179
+ controller variables and methods just as any controller action method. Each callback
180
180
  has access to the model through an instance variable using the model's name. So
181
181
  for instance if our model is :user, the instance variable is '@user'. Each
182
182
  wizard page action also defines a @title, @description and @step instance variable.
@@ -190,6 +190,59 @@ redirect caused by a button click in the view.
190
190
  Important: Method names for button callbacks will change if you change the name
191
191
  of the button. For general use, this is not an issue. See the Advanced Configuration section.
192
192
 
193
+ The order of callbacks for a GET request is as follows:
194
+
195
+ on_back
196
+ on_skip
197
+ on_cancel
198
+ ...on_'custom_button'...
199
+ on_get
200
+ render_wizard_form
201
+
202
+ Of course, only one of the button callbacks (back, skip or cancel) may occur for any single request, and
203
+ any one of them may keep the on_get from being called if they render or redirect.
204
+ :next and :finish button callbacks only occur for POST requests. The on_get callback
205
+ occurs just before rendering, and may itself render or redirect. The on_get callback
206
+ is an opportunity to modify or check the model fields before rendering.
207
+
208
+ The order of callbacks for a POST request is as follows:
209
+
210
+ on_post
211
+ on_back
212
+ on_skip
213
+ on_cancel
214
+ ...on_'custom_button'...
215
+ on_errors
216
+ render_wizard_form # only if errors
217
+ on_next
218
+ on_finish
219
+
220
+ In contrast to the on_get callback, the on_post callback occurs first. It is an
221
+ opportunity to modify the model instance values (the model instance has already been
222
+ created from the post parameters). The on_post method does not permit any rendering
223
+ or redirecting since the back, skip and cancel buttons have not been evaluated and
224
+ may require precedence over flow control. on_errors is called only for an invalid
225
+ form and the render callback (see below) is called only if there are errors. Either
226
+ on_next or on_finish are called if the form is valid. on_next is the default if a
227
+ 'Finish' button is not pressed. on_next by default moves to the next page, while
228
+ on_finish saves the model and redirects to the :completed redirect.
229
+
230
+ The argument of the callback macro indicates for which pages the block should be
231
+ called. You can indicate as many pages or :all as shown.
232
+
233
+ on_post(:step1) do
234
+ ...
235
+ end
236
+ on_back(:step2, :step3, :step4) do
237
+ ...
238
+ end
239
+ on_get(:all) do
240
+ ...
241
+ end
242
+
243
+ Indicating a form that does not exist raises a CallbackError.
244
+
245
+
193
246
  === Rendering Callback
194
247
 
195
248
  For anyone needing to handle rendering in a special way, wizardly provides a render
@@ -198,7 +251,7 @@ call back for this.
198
251
  class SignupController < ApplicationController
199
252
  act_wizardly_for :user, :redirect=>'/main'
200
253
 
201
- def render_wizard_page
254
+ def render_wizard_form
202
255
  respond_to do |format|
203
256
  format.html
204
257
  format.xml { render_xml(@step) }
@@ -24,6 +24,7 @@ module Wizardly
24
24
  self.class_eval @wizard_config.print_page_action_methods
25
25
  self.class_eval @wizard_config.print_callbacks
26
26
  self.class_eval @wizard_config.print_helpers
27
+ self.class_eval @wizard_config.print_callback_macros
27
28
  end
28
29
  end
29
30
 
@@ -14,7 +14,7 @@ module Wizardly
14
14
  @completed_redirect = opts[:redirect] || opts[:completed] || opts[:when_completed] #format_redirect(completed_redirect)
15
15
  @canceled_redirect = opts[:redirect] || opts[:canceled] || opts[:when_canceled]
16
16
  @allow_skipping = opts[:skip] || opts[:allow_skip] || opts[:allow_skipping] || false
17
- @guard = opts.key?(:guard) ? opts[:guard] : true
17
+ @guard_entry = opts.key?(:guard) ? opts[:guard] : true
18
18
  @password_fields = opts[:mask_fields] || opts[:mask_passwords] || [:password, :password_confirmation]
19
19
  @page_order = []
20
20
  @pages = {}
@@ -25,7 +25,6 @@ module Wizardly
25
25
  end
26
26
  end
27
27
 
28
- def guard?; @guard; end
29
28
  def model; @wizard_model_sym; end
30
29
  def model_instance_variable; "@#{@wizard_model_sym.to_s}"; end
31
30
  def model_class_name; @wizard_model_class_name; end
@@ -2,6 +2,40 @@ module Wizardly
2
2
  module Wizard
3
3
  class Configuration
4
4
 
5
+ def print_callback_macros
6
+ macros = [
7
+ %w(on_post on_post_%s_form),
8
+ %w(on_get on_get_%s_form),
9
+ %w(on_errors on_invalid_%s_form)
10
+ ]
11
+ self.buttons.each do |id, button|
12
+ macros << ['on_'+ id.to_s, 'on_%s_form_'+ id.to_s ]
13
+ end
14
+ mb = StringIO.new
15
+ macros.each do |macro|
16
+ mb << <<-MACRO
17
+ def self.#{macro.first}(*args, &block)
18
+ return if args.empty?
19
+ all_forms = #{page_order.inspect}
20
+ if args.include?(:all)
21
+ forms = all_forms
22
+ else
23
+ forms = args.map do |fa|
24
+ unless all_forms.include?(fa)
25
+ raise(ArgumentError, ":"+fa.to_s+" in callback #{macro.first} is not a form defined for the wizard", caller)
26
+ end
27
+ fa
28
+ end
29
+ end
30
+ forms.each do |form|
31
+ self.send(:define_method, sprintf("#{macro.last}", form.to_s), &block )
32
+ end
33
+ end
34
+ MACRO
35
+ end
36
+ mb.string
37
+ end
38
+
5
39
  def print_page_action_methods
6
40
  mb = StringIO.new
7
41
  self.pages.each do |id, p|
@@ -33,7 +67,7 @@ module Wizardly
33
67
  h = (flash[:wizard_model]||{}).merge(params[:#{self.model}] || {})
34
68
  @#{self.model} = #{self.model_class_name}.new(h)
35
69
  if request.post? && callback_performs_action?(:on_post_#{id}_form)
36
- raise CallbackError, "render or redirect not allowed in :filter_params_#{id}_page callback", caller
70
+ raise CallbackError, "render or redirect not allowed in :on_post_#{id}_form callback", caller
37
71
  end
38
72
  button_id = check_action_for_button
39
73
  return if performed?
@@ -130,7 +164,7 @@ ENSURE
130
164
  next_id = self.button_for_function(:next).id
131
165
  finish_id = self.button_for_function(:finish).id
132
166
  first_page = self.page_order.first
133
- guard_line = self.guard? ? '' : 'return #guard entry disabled'
167
+ guard_line = @guard_entry ? '' : 'return #guard entry disabled'
134
168
  <<-HELPERS
135
169
  protected
136
170
  def guard_entry
@@ -11,6 +11,8 @@ class <%= controller_class_name %> < ApplicationController
11
11
 
12
12
  <%= helper_methods %>
13
13
 
14
+ <%= callback_macro_methods %>
15
+
14
16
  private
15
17
  def methodize_button_name(value)
16
18
  value.to_s.strip.squeeze(' ').gsub(/ /, '_').downcase
@@ -43,6 +43,9 @@ class WizardlyControllerGenerator < Rails::Generator::Base
43
43
  def helper_methods
44
44
  @wizard_config.print_helpers
45
45
  end
46
+ def callback_macro_methods
47
+ @wizard_config.print_callback_macros
48
+ end
46
49
 
47
50
  protected
48
51
  # Override with your own usage banner.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jeffp-wizardly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Patmon
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-10 00:00:00 -07:00
12
+ date: 2009-08-11 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15