edk-wizardly 0.1.8.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. data/CHANGELOG.rdoc +38 -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/action_controller.rb +36 -0
  8. data/lib/wizardly/wizard/button.rb +35 -0
  9. data/lib/wizardly/wizard/configuration/methods.rb +414 -0
  10. data/lib/wizardly/wizard/configuration.rb +194 -0
  11. data/lib/wizardly/wizard/dsl.rb +27 -0
  12. data/lib/wizardly/wizard/page.rb +62 -0
  13. data/lib/wizardly/wizard/text_helpers.rb +16 -0
  14. data/lib/wizardly/wizard/utils.rb +11 -0
  15. data/lib/wizardly/wizard.rb +16 -0
  16. data/lib/wizardly.rb +31 -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 +100 -0
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'wizardly'
@@ -0,0 +1 @@
1
+ require 'wizardly'
@@ -0,0 +1,147 @@
1
+ module ValidationGroup
2
+ module ActiveRecord
3
+ module ActsMethods # extends ActiveRecord::Base
4
+ def self.extended(base)
5
+ # Add class accessor which is shared between all models and stores
6
+ # validation groups defined for each model
7
+ base.class_eval do
8
+ cattr_accessor :validation_group_classes
9
+ self.validation_group_classes = {}
10
+
11
+ def self.validation_group_order; @validation_group_order; end
12
+ def self.validation_groups(all_classes = false)
13
+ return (self.validation_group_classes[self] || {}) unless all_classes
14
+ klasses = ValidationGroup::Util.current_and_ancestors(self).reverse
15
+ returning Hash.new do |hash|
16
+ klasses.each do |klass|
17
+ hash.merge! self.validation_group_classes[klass]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ def validation_group(name, options={})
25
+ self_groups = (self.validation_group_classes[self] ||= {})
26
+ self_groups[name.to_sym] = case options[:fields]
27
+ when Array then options[:fields]
28
+ when Symbol, String then [options[:fields].to_sym]
29
+ else []
30
+ end
31
+ # jeffp: capture the declaration order for this class only (no
32
+ # superclasses)
33
+ (@validation_group_order ||= []) << name.to_sym
34
+
35
+ unless included_modules.include?(InstanceMethods)
36
+ # jeffp: added reader for current_validation_fields
37
+ attr_reader :current_validation_group, :current_validation_fields
38
+ include InstanceMethods
39
+ # jeffp: add valid?(group = nil), see definition below
40
+ alias_method_chain :valid?, :validation_group
41
+ end
42
+ end
43
+ end
44
+
45
+ module InstanceMethods # included in every model which calls validation_group
46
+ #needs testing
47
+ # def reset_fields_for_validation_group(group)
48
+ # group_classes = self.class.validation_group_classes
49
+ # found = ValidationGroup::Util.current_and_ancestors(self.class).find do |klass|
50
+ # group_classes[klass] && group_classes[klass].include?(group)
51
+ # end
52
+ # if found
53
+ # group_classes[found][group].each do |field|
54
+ # self[field] = nil
55
+ # end
56
+ # end
57
+ # end
58
+ def enable_validation_group(group)
59
+ # Check if given validation group is defined for current class or one of
60
+ # its ancestors
61
+ group_classes = self.class.validation_group_classes
62
+ found = ValidationGroup::Util.current_and_ancestors(self.class).
63
+ find do |klass|
64
+ group_classes[klass] && group_classes[klass].include?(group)
65
+ end
66
+ if found
67
+ @current_validation_group = group
68
+ # jeffp: capture current fields for performance optimization
69
+ @current_validation_fields = group_classes[found][group]
70
+ else
71
+ raise ArgumentError, "No validation group of name :#{group}"
72
+ end
73
+ end
74
+
75
+ def disable_validation_group
76
+ @current_validation_group = nil
77
+ # jeffp: delete fields
78
+ @current_validation_fields = nil
79
+ end
80
+
81
+ def reject_non_validation_group_errors
82
+ return unless validation_group_enabled?
83
+ self.errors.remove_on(@current_validation_fields)
84
+ end
85
+
86
+ # jeffp: optimizer for someone writing custom :validate method -- no need
87
+ # to validate fields outside the current validation group note: could also
88
+ # use in validation modules to improve performance
89
+ def should_validate?(attribute)
90
+ !self.validation_group_enabled? || (@current_validation_fields && @current_validation_fields.include?(attribute.to_sym))
91
+ end
92
+
93
+ def validation_group_enabled?
94
+ respond_to?(:current_validation_group) && !current_validation_group.nil?
95
+ end
96
+
97
+ # eliminates need to use :enable_validation_group before :valid? call --
98
+ # nice
99
+ def valid_with_validation_group?(group=nil)
100
+ self.enable_validation_group(group) if group
101
+ valid_without_validation_group?
102
+ end
103
+ end
104
+
105
+ module Errors # included in ActiveRecord::Errors
106
+ def add_with_validation_group(attribute,
107
+ msg = @@default_error_messages[:invalid], *args,
108
+ &block)
109
+ # jeffp: setting @current_validation_fields and use of should_validate? optimizes code
110
+ add_error = @base.respond_to?(:should_validate?) ? @base.should_validate?(attribute.to_sym) : true
111
+ add_without_validation_group(attribute, msg, *args, &block) if add_error
112
+ end
113
+
114
+ def remove_on(attributes)
115
+ return unless attributes
116
+ attributes = [attributes] unless attributes.is_a?(Array)
117
+ @errors.reject!{|k,v| !attributes.include?(k.to_sym)}
118
+ end
119
+
120
+ def self.included(base) #:nodoc:
121
+ base.class_eval do
122
+ alias_method_chain :add, :validation_group
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ module Util
129
+ # Return array consisting of current and its superclasses down to and
130
+ # including base_class.
131
+ def self.current_and_ancestors(current)
132
+ returning [] do |klasses|
133
+ klasses << current
134
+ root = current.base_class
135
+ until current == root
136
+ current = current.superclass
137
+ klasses << current
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ # jeffp: moved from init.rb for gemification purposes --
145
+ # require 'validation_group' loads everything now, init.rb requires 'validation_group' only
146
+ ActiveRecord::Base.send(:extend, ValidationGroup::ActiveRecord::ActsMethods)
147
+ ActiveRecord::Errors.send :include, ValidationGroup::ActiveRecord::Errors
@@ -0,0 +1,36 @@
1
+ require 'wizardly/wizard'
2
+
3
+ module Wizardly
4
+ module ActionController
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+
8
+ base.class_eval do
9
+ before_filter :guard_entry
10
+ class << self
11
+ attr_reader :wizard_config #note: reader for @wizard_config on the class (not the instance)
12
+ end
13
+ hide_action :reset_wizard_session_vars, :wizard_config, :methodize_button_name
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+ private
19
+ def configure_wizard_for_model(model, opts={}, &block)
20
+
21
+ # controller_name = self.name.sub(/Controller$/, '').underscore.to_sym
22
+ @wizard_config = Wizardly::Wizard::Configuration.create(controller_name, model, opts, &block)
23
+ # define methods
24
+ self.class_eval @wizard_config.print_page_action_methods
25
+ self.class_eval @wizard_config.print_callbacks
26
+ self.class_eval @wizard_config.print_helpers
27
+ self.class_eval @wizard_config.print_callback_macros
28
+ end
29
+ end
30
+
31
+ # instance methods for controller
32
+ public
33
+ def wizard_config; self.class.wizard_config; end
34
+
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ require 'wizardly/wizard/text_helpers'
2
+
3
+ module Wizardly
4
+ module Wizard
5
+ class Button
6
+ include TextHelpers
7
+ attr_reader :name
8
+ attr_reader :id
9
+
10
+ def initialize(id, name=nil)
11
+ @id = id
12
+ @name = name || symbol_to_button_name(id)
13
+ @user_defined = false
14
+ end
15
+
16
+ def user_defined?; @user_defined; end
17
+
18
+ #used in the dsl
19
+ def name_to(name, opts={})
20
+ case name
21
+ when String then @name = name.strip.squeeze(' ')
22
+ when Symbol then @name = symbol_to_button_name(name)
23
+ end
24
+ @id = opts[:id] if (opts[:id] && opts[:id].is_a?(Symbol))
25
+ end
26
+ end
27
+
28
+ class UserDefinedButton < Button
29
+ def initialize(id, name=nil)
30
+ super
31
+ @user_defined = true
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,414 @@
1
+ module Wizardly
2
+ module Wizard
3
+ class Configuration
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
+ self._define_action_callback_macro('#{macro.first}', '#{macro.last}', *args, &block)
19
+ end
20
+ MACRO
21
+ end
22
+ mb << <<-DEFMAC
23
+ def self._define_action_callback_macro(macro_first, macro_last, *args, &block)
24
+ return if args.empty?
25
+ all_forms = #{page_order.inspect}
26
+ if args.include?(:all)
27
+ forms = all_forms
28
+ else
29
+ forms = args.map do |fa|
30
+ unless all_forms.include?(fa)
31
+ raise(ArgumentError, ":"+fa.to_s+" in callback '" + macro_first + "' is not a form defined for the wizard", caller)
32
+ end
33
+ fa
34
+ end
35
+ end
36
+ forms.each do |form|
37
+ self.send(:define_method, sprintf(macro_last, form.to_s), &block )
38
+ hide_action macro_last.to_sym
39
+ end
40
+ end
41
+
42
+ DEFMAC
43
+
44
+ [
45
+ %w(on_completed _after_wizard_save)
46
+ ].each do |macro|
47
+ mb << <<-EVENTS
48
+ def self.#{macro.first}(&block)
49
+ self.send(:define_method, :#{macro.last}, &block )
50
+ end
51
+ EVENTS
52
+ end
53
+ mb.string
54
+ end
55
+
56
+ def print_page_action_methods
57
+ mb = StringIO.new
58
+ self.pages.each do |id, p|
59
+ mb << <<-COMMENT
60
+
61
+ # #{id} action method
62
+ #{self.print_page_action_method(id)}
63
+ COMMENT
64
+ end
65
+ mb << <<-INDEX
66
+ def index
67
+ redirect_to :action=>:#{self.page_order.first}
68
+ end
69
+
70
+ INDEX
71
+ mb.string
72
+ end
73
+
74
+ def initial_referer_key
75
+ @initial_referer_key ||= "#{self.controller_path.sub(/\//, '')}_irk".to_sym
76
+ end
77
+ def persist_key;
78
+ @persist_key ||= "#{self.controller_path.sub(/\//, '')}_dat".to_sym
79
+ end
80
+ def progression_key
81
+ @progression_key ||= "#{self.controller_path.sub(/\//, '')}_prg".to_sym
82
+ end
83
+
84
+ def print_page_action_method(id)
85
+ page = @pages[id]
86
+ finish_button = self.button_for_function(:finish).id
87
+ next_button = self.button_for_function(:next).id
88
+
89
+ (mb = StringIO.new) << <<-ONE
90
+ def #{page.name}
91
+ begin
92
+ @step = :#{id}
93
+ @wizard = wizard_config
94
+ @title = '#{page.title}'
95
+ @description = '#{page.description}'
96
+ _build_wizard_model
97
+ if request.post? && callback_performs_action?(:_on_post_#{id}_form)
98
+ raise CallbackError, "render or redirect not allowed in :on_post(:#{id}) callback", caller
99
+ end
100
+ button_id = check_action_for_button
101
+ return if performed?
102
+ if request.get?
103
+ return if callback_performs_action?(:_on_get_#{id}_form)
104
+ render_wizard_form
105
+ return
106
+ end
107
+
108
+ # @#{self.model}.enable_validation_group :#{id}
109
+ unless @#{self.model}.valid?(:#{id})
110
+ return if callback_performs_action?(:_on_invalid_#{id}_form)
111
+ render_wizard_form
112
+ return
113
+ end
114
+
115
+ @do_not_complete = false
116
+ ONE
117
+ if self.last_page?(id)
118
+ mb << <<-TWO
119
+ callback_performs_action?(:_on_#{id}_form_#{finish_button})
120
+ complete_wizard unless @do_not_complete
121
+ TWO
122
+ elsif self.first_page?(id)
123
+ mb << <<-THREE
124
+ if button_id == :#{finish_button}
125
+ callback_performs_action?(:_on_#{id}_form_#{finish_button})
126
+ complete_wizard unless @do_not_complete
127
+ return
128
+ end
129
+ return if callback_performs_action?(:_on_#{id}_form_#{next_button})
130
+ redirect_to :action=>:#{self.next_page(id)}
131
+ THREE
132
+ else
133
+ mb << <<-FOUR
134
+ if button_id == :#{finish_button}
135
+ callback_performs_action?(:_on_#{id}_form_#{finish_button})
136
+ complete_wizard unless @do_not_complete
137
+ return
138
+ end
139
+ return if callback_performs_action?(:_on_#{id}_form_#{next_button})
140
+ redirect_to :action=>:#{self.next_page(id)}
141
+ FOUR
142
+ end
143
+
144
+ mb << <<-ENSURE
145
+ ensure
146
+ _preserve_wizard_model
147
+ end
148
+ end
149
+ ENSURE
150
+ mb.string
151
+ end
152
+
153
+ def print_callbacks
154
+ finish = self.button_for_function(:finish).id
155
+ skip = self.button_for_function(:skip).id
156
+ back = self.button_for_function(:back).id
157
+ cancel = self.button_for_function(:cancel).id
158
+ <<-CALLBACKS
159
+ protected
160
+ def _on_wizard_#{finish}
161
+ return if @wizard_completed_flag
162
+ @#{self.model}.save_without_validation! if @#{self.model}.changed?
163
+ @wizard_completed_flag = true
164
+ reset_wizard_form_data
165
+ _wizard_final_redirect_to(:completed)
166
+ end
167
+ def _on_wizard_#{skip}
168
+ self.progression = self.progression - [@step]
169
+ redirect_to(:action=>wizard_config.next_page(@step)) unless self.performed?
170
+ end
171
+ def _on_wizard_#{back}
172
+ redirect_to(:action=>(previous_in_progression_from(@step) || :#{self.page_order.first})) unless self.performed?
173
+ end
174
+ def _on_wizard_#{cancel}
175
+ _wizard_final_redirect_to(:canceled)
176
+ end
177
+ def _wizard_final_redirect_to(type)
178
+ init = (type == :canceled && wizard_config.form_data_keep_in_session?) ?
179
+ self.initial_referer :
180
+ reset_wizard_session_vars
181
+ unless self.performed?
182
+ redir = (type == :canceled ? wizard_config.canceled_redirect : wizard_config.completed_redirect) || init
183
+ return redirect_to(redir) if redir
184
+ raise Wizardly::RedirectNotDefinedError, "No redirect was defined for completion or canceling the wizard. Use :completed and :canceled options to define redirects.", caller
185
+ end
186
+ end
187
+ hide_action :_on_wizard_#{finish}, :_on_wizard_#{skip}, :_on_wizard_#{back}, :_on_wizard_#{cancel}, :_wizard_final_redirect_to
188
+ CALLBACKS
189
+ end
190
+
191
+ def print_helpers
192
+ next_id = self.button_for_function(:next).id
193
+ finish_id = self.button_for_function(:finish).id
194
+ first_page = self.page_order.first
195
+ finish_button = self.button_for_function(:finish).id
196
+ guard_line = self.guard? ? '' : 'return check_progression #guard entry disabled'
197
+ mb = StringIO.new
198
+ mb << <<-PROGRESSION
199
+ protected
200
+ def do_not_complete; @do_not_complete = true; end
201
+ def previous_in_progression_from(step)
202
+ po = #{self.page_order.inspect}
203
+ p = self.progression
204
+ p -= po[po.index(step)..-1]
205
+ self.progression = p
206
+ p.last
207
+ end
208
+ def check_progression
209
+ p = self.progression
210
+ a = params[:action].to_sym
211
+ return if p.last == a
212
+ po = #{self.page_order.inspect}
213
+ return unless (ai = po.index(a))
214
+ p -= po[ai..-1]
215
+ p << a
216
+ self.progression = p
217
+ end
218
+ PROGRESSION
219
+ if self.form_data_keep_in_session?
220
+ mb << <<-SESSION
221
+ # for :form_data=>:session
222
+ def guard_entry
223
+ if (r = request.env['HTTP_REFERER'])
224
+ h = ::ActionController::Routing::Routes.recognize_path(URI.parse(r).path)
225
+ return check_progression if (h[:controller].split('/').last||'') == '#{self.controller_name}'
226
+ self.initial_referer = h unless self.initial_referer
227
+ end
228
+ # coming from outside the controller
229
+ #{guard_line}
230
+ if (params[:action] == '#{first_page}' || params[:action] == 'index')
231
+ return check_progression
232
+ elsif self.wizard_form_data
233
+ p = self.progression
234
+ return check_progression if p.include?(params[:action].to_sym)
235
+ return redirect_to(:action=>(p.last||:#{first_page}))
236
+ end
237
+ redirect_to :action=>:#{first_page}
238
+ end
239
+ hide_action :guard_entry
240
+
241
+ SESSION
242
+ else
243
+ mb << <<-SANDBOX
244
+ # for :form_data=>:sandbox
245
+ def guard_entry
246
+ if (r = request.env['HTTP_REFERER'])
247
+ h = ::ActionController::Routing::Routes.recognize_path(URI.parse(r).path)
248
+ return check_progression if (h[:controller].split('/').last||'') == '#{self.controller_name}'
249
+ self.initial_referer = h
250
+ else
251
+ self.initial_referer = nil
252
+ end
253
+ # coming from outside the controller
254
+ reset_wizard_form_data
255
+ #{guard_line}
256
+ return redirect_to(:action=>:#{first_page}) unless (params[:action] || '') == '#{first_page}'
257
+ check_progression
258
+ end
259
+ hide_action :guard_entry
260
+
261
+ SANDBOX
262
+ end
263
+ mb << <<-HELPERS
264
+ def render_and_return
265
+ return if callback_performs_action?('_on_get_'+@step.to_s+'_form')
266
+ render_wizard_form
267
+ render unless self.performed?
268
+ end
269
+
270
+ def complete_wizard(redirect = nil)
271
+ unless @wizard_completed_flag
272
+ @#{self.model}.save_without_validation!
273
+ callback_performs_action?(:_after_wizard_save)
274
+ end
275
+ redirect_to redirect if (redirect && !self.performed?)
276
+ return if @wizard_completed_flag
277
+ _on_wizard_#{finish_button}
278
+ redirect_to(#{Utils.formatted_redirect(self.completed_redirect)}) unless self.performed?
279
+ end
280
+ def _build_wizard_model
281
+ if self.wizard_config.persist_model_per_page?
282
+ h = self.wizard_form_data
283
+ if (h && model_id = h['id'])
284
+ _model = #{self.model_class_name}.find(model_id)
285
+ _model.attributes = params[:#{self.model}]||{}
286
+ @#{self.model} = _model
287
+ return
288
+ end
289
+ @#{self.model} = #{self.model_class_name}.new(params[:#{self.model}])
290
+ else # persist data in session or flash
291
+ h = (self.wizard_form_data||{}).merge(params[:#{self.model}] || {})
292
+ @#{self.model} = #{self.model_class_name}.new(h)
293
+ end
294
+ end
295
+ def _preserve_wizard_model
296
+ return unless (@#{self.model} && !@wizard_completed_flag)
297
+ if self.wizard_config.persist_model_per_page?
298
+ @#{self.model}.save_without_validation!
299
+ if request.get?
300
+ @#{self.model}.errors.clear
301
+ else
302
+ @#{self.model}.reject_non_validation_group_errors
303
+ end
304
+ self.wizard_form_data = {'id'=>@#{self.model}.id}
305
+ else
306
+ self.wizard_form_data = @#{self.model}.attributes
307
+ end
308
+ end
309
+ hide_action :_build_wizard_model, :_preserve_wizard_model
310
+
311
+ def initial_referer
312
+ session[:#{self.initial_referer_key}]
313
+ end
314
+ def initial_referer=(val)
315
+ session[:#{self.initial_referer_key}] = val
316
+ end
317
+ def progression=(array)
318
+ session[:#{self.progression_key}] = array
319
+ end
320
+ def progression
321
+ session[:#{self.progression_key}]||[]
322
+ end
323
+ hide_action :progression, :progression=, :initial_referer, :initial_referer=
324
+
325
+ def wizard_form_data=(hash)
326
+ if wizard_config.form_data_keep_in_session?
327
+ session[:#{self.persist_key}] = hash
328
+ else
329
+ if hash
330
+ flash[:#{self.persist_key}] = hash
331
+ else
332
+ flash.discard(:#{self.persist_key})
333
+ end
334
+ end
335
+ end
336
+
337
+ def reset_wizard_form_data; self.wizard_form_data = nil; end
338
+ def wizard_form_data
339
+ wizard_config.form_data_keep_in_session? ? session[:#{self.persist_key}] : flash[:#{self.persist_key}]
340
+ end
341
+ hide_action :wizard_form_data, :wizard_form_data=, :reset_wizard_form_data
342
+
343
+ def render_wizard_form
344
+ end
345
+ hide_action :render_wizard_form
346
+
347
+ def performed?; super; end
348
+ hide_action :performed?
349
+
350
+ def underscore_button_name(value)
351
+ value.to_s.strip.squeeze(' ').gsub(/ /, '_').downcase
352
+ end
353
+ hide_action :underscore_button_name
354
+
355
+ def reset_wizard_session_vars
356
+ self.progression = nil
357
+ init = self.initial_referer
358
+ self.initial_referer = nil
359
+ init
360
+ end
361
+ hide_action :reset_wizard_session_vars
362
+
363
+ def check_action_for_button
364
+ button_id = nil
365
+ case
366
+ when params[:commit]
367
+ button_name = params[:commit]
368
+ button_id = underscore_button_name(button_name).to_sym
369
+ when ((b_ar = self.wizard_config.buttons.find{|k,b| params[k]}) && params[b_ar.first] == b_ar.last.name)
370
+ button_name = b_ar.last.name
371
+ button_id = b_ar.first
372
+ end
373
+ if button_id
374
+ unless [:#{next_id}, :#{finish_id}].include?(button_id)
375
+ action_method_name = "_on_" + params[:action].to_s + "_form_" + button_id.to_s
376
+ callback_performs_action?(action_method_name)
377
+ unless ((btn_obj = self.wizard_config.buttons[button_id]) == nil || btn_obj.user_defined?)
378
+ method_name = "_on_wizard_" + button_id.to_s
379
+ if (self.method(method_name))
380
+ self.__send__(method_name)
381
+ else
382
+ raise MissingCallbackError, "Callback method either '" + action_method_name + "' or '" + method_name + "' not defined", caller
383
+ end
384
+ end
385
+ end
386
+ end
387
+ button_id
388
+ end
389
+ hide_action :check_action_for_button
390
+
391
+ @wizard_callbacks ||= []
392
+ def self.wizard_callbacks; @wizard_callbacks; end
393
+
394
+ def callback_performs_action?(methId)
395
+ cache = self.class.wizard_callbacks
396
+ return false if cache.include?(methId)
397
+
398
+ begin
399
+ self.send(methId)
400
+ rescue NoMethodError
401
+ cache << methId
402
+ return false
403
+ end
404
+
405
+ self.performed?
406
+ end
407
+ hide_action :callback_performs_action?
408
+
409
+ HELPERS
410
+ mb.string
411
+ end
412
+ end
413
+ end
414
+ end