hat-trick 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +5 -5
- data/app/assets/javascripts/hat-trick.js.coffee +254 -120
- data/app/views/hat_trick/_wizard_meta.html.erb +1 -1
- data/hat-trick.gemspec +3 -3
- data/lib/hat-trick.rb +1 -1
- data/lib/hat_trick/config.rb +17 -0
- data/lib/hat_trick/controller_helpers.rb +64 -0
- data/lib/hat_trick/controller_hooks.rb +20 -64
- data/lib/hat_trick/dsl.rb +86 -62
- data/lib/hat_trick/{rails_engine.rb → engine.rb} +1 -1
- data/lib/hat_trick/form_helper.rb +0 -4
- data/lib/hat_trick/model_methods.rb +30 -8
- data/lib/hat_trick/step_definition.rb +12 -12
- data/lib/hat_trick/version.rb +1 -1
- data/lib/hat_trick/wizard.rb +44 -27
- data/lib/hat_trick/wizard_definition.rb +2 -0
- data/lib/hat_trick/wizard_steps.rb +5 -2
- data/spec/lib/hat_trick/dsl_spec.rb +26 -0
- data/spec/lib/hat_trick/wizard_spec.rb +21 -19
- data/spec/spec_helper.rb +1 -9
- data/vendor/assets/javascripts/jquery.form.wizard.js +499 -438
- data/vendor/assets/javascripts/jquery.history.js +1 -0
- metadata +15 -12
- data/spec/lib/hat_trick/step_spec.rb +0 -9
- data/vendor/assets/javascripts/jquery.ba-bbq.js +0 -1137
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'hat_trick/model_methods'
|
2
|
+
require 'hat_trick/controller_helpers'
|
2
3
|
|
3
4
|
module HatTrick
|
4
5
|
module ControllerHooks
|
5
6
|
extend ActiveSupport::Concern
|
7
|
+
include ControllerHelpers
|
6
8
|
|
7
9
|
included do
|
8
10
|
alias_method_chain :render, :hat_trick
|
@@ -10,12 +12,12 @@ module HatTrick
|
|
10
12
|
|
11
13
|
def self.def_action_method_aliases(action_methods)
|
12
14
|
action_methods.each do |meth|
|
13
|
-
Rails.logger.info "Aliasing #{meth}"
|
15
|
+
# Rails.logger.info "Aliasing #{meth}"
|
14
16
|
module_eval <<-RUBY_EVAL
|
15
17
|
def #{meth}_with_hat_trick(*args)
|
16
18
|
Rails.logger.info "#{meth}_with_hat_trick called"
|
17
19
|
#{meth}_hook(*args) if respond_to?("#{meth}_hook", :include_private)
|
18
|
-
common_hook(*args)
|
20
|
+
common_hook(*args) if respond_to?(:common_hook, :include_private)
|
19
21
|
#{meth}_without_hat_trick(*args)
|
20
22
|
end
|
21
23
|
private "#{meth}_with_hat_trick"
|
@@ -26,53 +28,6 @@ module HatTrick
|
|
26
28
|
|
27
29
|
private
|
28
30
|
|
29
|
-
def params_model_name
|
30
|
-
params.each do |k,v|
|
31
|
-
return class_name(k) if v.is_a?(Hash) && is_model?(k)
|
32
|
-
end
|
33
|
-
nil
|
34
|
-
end
|
35
|
-
|
36
|
-
def is_model?(model_name)
|
37
|
-
begin
|
38
|
-
class_name(model_name).constantize
|
39
|
-
rescue NameError
|
40
|
-
return false
|
41
|
-
end
|
42
|
-
true
|
43
|
-
end
|
44
|
-
|
45
|
-
def class_name(hash_key)
|
46
|
-
hash_key.to_s.camelize
|
47
|
-
end
|
48
|
-
|
49
|
-
def model_class
|
50
|
-
model_name = params_model_name
|
51
|
-
return nil if model_name.nil?
|
52
|
-
begin
|
53
|
-
model_class = params_model_name.constantize
|
54
|
-
rescue NameError
|
55
|
-
Rails.logger.error "Could not find model class #{params_model_name.camelize}"
|
56
|
-
nil
|
57
|
-
else
|
58
|
-
model_class
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def setup_validation_group_for(wizard_step)
|
63
|
-
klass = model_class
|
64
|
-
return if klass.nil?
|
65
|
-
step_name = wizard_step.name
|
66
|
-
validation_groups = ::ActiveRecord::Base.validation_group_classes[klass] || []
|
67
|
-
unless validation_groups.include?(step_name)
|
68
|
-
klass.validation_group(step_name, :fields => params.keys)
|
69
|
-
end
|
70
|
-
HatTrick::ModelMethods.set_current_validation_group_for(model_class, step_name)
|
71
|
-
unless klass.included_modules.include?(HatTrick::ModelMethods)
|
72
|
-
klass.send(:include, HatTrick::ModelMethods)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
31
|
def create_hook(*args)
|
77
32
|
setup_validation_group_for(ht_wizard.current_step)
|
78
33
|
end
|
@@ -81,13 +36,10 @@ module HatTrick
|
|
81
36
|
setup_validation_group_for(ht_wizard.current_step)
|
82
37
|
end
|
83
38
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
def render_with_hat_trick(*args)
|
89
|
-
if args.first.has_key?(:json)
|
90
|
-
model = args[0][:json]
|
39
|
+
def render_with_hat_trick(*args, &block)
|
40
|
+
rendered = args.first
|
41
|
+
if rendered && rendered.has_key?(:json)
|
42
|
+
model = rendered[:json]
|
91
43
|
ht_wizard.model = model
|
92
44
|
end
|
93
45
|
|
@@ -102,17 +54,21 @@ module HatTrick
|
|
102
54
|
:currentStep => ht_wizard.current_step,
|
103
55
|
}
|
104
56
|
|
105
|
-
|
106
|
-
|
57
|
+
include_data = ht_wizard.include_data
|
58
|
+
|
59
|
+
# this sets the gon data (JS hatTrick object) for the initial page load
|
60
|
+
gon.metadata = wizard_metadata
|
61
|
+
gon.data = include_data
|
62
|
+
gon.model = ht_wizard.model
|
107
63
|
|
108
|
-
|
109
|
-
|
110
|
-
args[0][:json] = { :
|
111
|
-
:
|
112
|
-
args[0][:json].merge!
|
64
|
+
# this sets the wizard metadata for subsequent AJAX requests
|
65
|
+
if ht_wizard.model && rendered.has_key?(:json)
|
66
|
+
args[0][:json] = { :model => ht_wizard.model,
|
67
|
+
:metadata => wizard_metadata }
|
68
|
+
args[0][:json].merge!( :data => include_data )
|
113
69
|
end
|
114
70
|
|
115
|
-
render_without_hat_trick(*args)
|
71
|
+
render_without_hat_trick(*args, &block)
|
116
72
|
end
|
117
73
|
end
|
118
74
|
end
|
data/lib/hat_trick/dsl.rb
CHANGED
@@ -1,75 +1,74 @@
|
|
1
1
|
require 'hat_trick/wizard_definition'
|
2
2
|
require 'hat_trick/controller_hooks'
|
3
|
+
require 'hat_trick/config'
|
3
4
|
|
4
5
|
module HatTrick
|
5
6
|
module DSL
|
6
7
|
extend ActiveSupport::Concern
|
7
8
|
|
8
|
-
|
9
|
-
def wizard(&block)
|
10
|
-
if block_given?
|
11
|
-
include HatTrick::DSL::ControllerInstanceMethods
|
12
|
-
include HatTrick::ControllerHooks
|
9
|
+
attr_accessor :ht_wizard, :configure_callback, :_ht_config
|
13
10
|
|
14
|
-
|
11
|
+
delegate :model, :previously_visited_step, :to => :ht_wizard
|
15
12
|
|
16
|
-
|
17
|
-
|
13
|
+
included do
|
14
|
+
alias_method_chain :initialize, :hat_trick
|
15
|
+
end
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
def initialize_with_hat_trick(*args)
|
18
|
+
@_ht_config = HatTrick::Config.new(self.class.wizard_def)
|
19
|
+
if configure_callback.is_a?(Proc)
|
20
|
+
ht_wizard.controller.instance_exec(@_ht_config, &configure_callback)
|
22
21
|
end
|
22
|
+
initialize_without_hat_trick(*args)
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
def next_step(name=nil)
|
26
|
+
if name.nil?
|
27
|
+
# getter
|
28
|
+
ht_wizard.next_step
|
29
|
+
else
|
30
|
+
# setter
|
31
|
+
step = ht_wizard.find_step(name)
|
32
|
+
# explicitly set steps should not be skipped
|
33
|
+
step.skipped = false
|
34
|
+
ht_wizard.current_step.next_step = step
|
30
35
|
end
|
36
|
+
end
|
31
37
|
|
32
|
-
|
38
|
+
def skip_this_step
|
39
|
+
ht_wizard.skip_step(ht_wizard.current_step)
|
40
|
+
end
|
33
41
|
|
34
|
-
|
42
|
+
module ClassMethods
|
43
|
+
attr_reader :wizard_def
|
35
44
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
45
|
+
def wizard(&block)
|
46
|
+
if block_given?
|
47
|
+
include HatTrick::DSL::ControllerInstanceMethods
|
48
|
+
include HatTrick::ControllerHooks
|
39
49
|
|
40
|
-
|
41
|
-
step_name = params['_ht_meta']['step']
|
42
|
-
@ht_wizard.current_step = step_name if step_name
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
50
|
+
@wizard_def = HatTrick::WizardDefinition.new
|
46
51
|
|
47
|
-
|
48
|
-
attr_reader :wizard_def
|
49
|
-
attr_accessor :wizard
|
52
|
+
yield
|
50
53
|
|
51
|
-
|
54
|
+
else
|
55
|
+
raise ArgumentError, "wizard called without a block"
|
56
|
+
end
|
57
|
+
end
|
52
58
|
|
53
|
-
def
|
54
|
-
|
59
|
+
def configure(&block)
|
60
|
+
raise "Must pass a block to configure" unless block_given?
|
61
|
+
@config_callback = block
|
55
62
|
end
|
56
63
|
|
57
64
|
def step(name, args={}, &block)
|
65
|
+
raise "step must be called from within a wizard block" unless wizard_def
|
58
66
|
wizard_def.add_step(name, args)
|
59
67
|
instance_eval &block if block_given?
|
60
68
|
end
|
61
69
|
|
62
|
-
def next_step(name=nil)
|
63
|
-
if name.nil?
|
64
|
-
wizard.next_step
|
65
|
-
else
|
66
|
-
raise "next_step should only be called from an after block" if wizard.nil?
|
67
|
-
step = wizard.find_step(name)
|
68
|
-
wizard.current_step.next_step = step
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
70
|
def repeat_step(name)
|
71
|
+
raise "repeat_step must be called from within a wizard block" unless wizard_def
|
73
72
|
repeated_step = wizard_def.find_step(name)
|
74
73
|
raise ArgumentError, "Couldn't find step named #{name}" unless repeated_step
|
75
74
|
new_step = repeated_step.dup
|
@@ -77,47 +76,72 @@ module HatTrick
|
|
77
76
|
new_step.fieldset = repeated_step.fieldset
|
78
77
|
# but use the current step's name
|
79
78
|
new_step.name = wizard_def.last_step.name
|
80
|
-
|
81
|
-
|
82
|
-
# rid of this wizard / wizard_def distinction
|
83
|
-
else
|
84
|
-
# replace the step we're in the middle of defining w/ new_step
|
85
|
-
wizard_def.replace_step(wizard_def.last_step, new_step)
|
86
|
-
end
|
79
|
+
# replace the step we're in the middle of defining w/ new_step
|
80
|
+
wizard_def.replace_step(wizard_def.last_step, new_step)
|
87
81
|
end
|
88
82
|
|
89
83
|
def skip_this_step
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
# can be explicitly jumped to, but won't be in the normal flow
|
95
|
-
wizard_def.last_step.skipped = true
|
96
|
-
end
|
84
|
+
# skip_this_step in wizard definition (class) context means the step
|
85
|
+
# can be explicitly jumped to, but won't be visited in the normal flow
|
86
|
+
raise "skip_this_step must be called from within a wizard block" unless wizard_def
|
87
|
+
wizard_def.last_step.skipped = true
|
97
88
|
end
|
98
89
|
|
99
90
|
def button_to(name, options=nil)
|
100
|
-
|
101
|
-
raise "button_to not yet supported in before/after blocks"
|
102
|
-
end
|
91
|
+
raise "button_to must be called from within a wizard block" unless wizard_def
|
103
92
|
label = options[:label] if options
|
104
93
|
label ||= name.to_s.humanize
|
94
|
+
|
95
|
+
id = options[:id] if options
|
96
|
+
|
105
97
|
step = wizard_def.last_step
|
106
|
-
|
98
|
+
button = { :label => label }
|
99
|
+
button[:id] = id unless id.nil?
|
100
|
+
step.buttons = step.buttons.merge(name => button)
|
107
101
|
end
|
108
102
|
|
109
103
|
def before(&block)
|
104
|
+
raise "before must be called from within a wizard block" unless wizard_def
|
110
105
|
wizard_def.last_step.before_callback = block
|
111
106
|
end
|
112
107
|
|
113
108
|
def after(&block)
|
109
|
+
raise "after must be called from within a wizard block" unless wizard_def
|
114
110
|
wizard_def.last_step.after_callback = block
|
115
111
|
end
|
116
112
|
|
117
113
|
def include_data(key, &block)
|
114
|
+
raise "include_data must be called from within a wizard block" unless wizard_def
|
118
115
|
wizard_def.last_step.include_data = { key.to_sym => block }
|
119
116
|
end
|
117
|
+
|
118
|
+
def set_contents(&block)
|
119
|
+
raise "set_contents must be called from within a wizard block" unless wizard_def
|
120
|
+
current_step_name = wizard_def.last_step.to_sym
|
121
|
+
include_data "hat_trick_step_contents" do |wiz, model|
|
122
|
+
{ current_step_name => instance_exec(wiz, model, &block) }
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
module ControllerInstanceMethods
|
128
|
+
extend ActiveSupport::Concern
|
129
|
+
|
130
|
+
included do
|
131
|
+
before_filter :setup_wizard
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def setup_wizard
|
137
|
+
wizard_def = self.class.instance_variable_get("@wizard_def")
|
138
|
+
@ht_wizard = wizard_def.get_wizard(self)
|
139
|
+
|
140
|
+
if params.has_key?('_ht_meta')
|
141
|
+
step_name = params['_ht_meta']['step']
|
142
|
+
@ht_wizard.current_step = step_name if step_name
|
143
|
+
end
|
144
|
+
end
|
120
145
|
end
|
121
146
|
end
|
122
147
|
end
|
123
|
-
|
@@ -7,10 +7,6 @@ module HatTrick
|
|
7
7
|
wizard = controller.send(:ht_wizard)
|
8
8
|
wizard.start unless wizard.started?
|
9
9
|
|
10
|
-
# Do we still need these 2 lines?
|
11
|
-
wizard.model = record
|
12
|
-
controller.gon.form_model = record
|
13
|
-
|
14
10
|
options[:url] = wizard.current_form_url
|
15
11
|
options[:method] = wizard.current_form_method.to_sym
|
16
12
|
|
@@ -1,24 +1,46 @@
|
|
1
1
|
module HatTrick
|
2
2
|
module ModelMethods
|
3
3
|
extend ActiveSupport::Concern
|
4
|
-
mattr_accessor :
|
4
|
+
mattr_accessor :validation_groups
|
5
|
+
|
6
|
+
attr_accessor :_dummy # so the dummy field will have something to set
|
5
7
|
|
6
8
|
included do
|
7
|
-
alias_method_chain :
|
9
|
+
alias_method_chain :perform_validations, :hat_trick if instance_methods.include?(:perform_validations)
|
10
|
+
alias_method_chain :as_json, :model_name if instance_methods.include?(:as_json)
|
8
11
|
end
|
9
12
|
|
10
13
|
def self.set_current_validation_group_for(klass, validation_group_name)
|
11
|
-
self.
|
12
|
-
|
14
|
+
self.validation_groups ||= {}
|
15
|
+
validation_groups[klass.to_s.underscore] = validation_group_name
|
13
16
|
end
|
14
17
|
|
15
18
|
def self.current_validation_group_for(klass)
|
16
|
-
|
19
|
+
return nil unless validation_groups
|
20
|
+
validation_groups[klass.to_s.underscore]
|
21
|
+
end
|
22
|
+
|
23
|
+
def perform_validations_with_hat_trick(*args, &block)
|
24
|
+
enable_current_validation_group
|
25
|
+
perform_validations_without_hat_trick(*args, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def as_json_with_model_name(*args, &block)
|
29
|
+
json = as_json_without_model_name(*args, &block)
|
30
|
+
json.merge! :__name__ => self.class.to_s.underscore if json.respond_to?(:merge!)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# don't call this method 'current_validation_group', it conflicts with
|
36
|
+
# the gem
|
37
|
+
def current_step_validation_group
|
38
|
+
HatTrick::ModelMethods.current_validation_group_for(self.class)
|
17
39
|
end
|
18
40
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
41
|
+
def enable_current_validation_group
|
42
|
+
validation_group = current_step_validation_group
|
43
|
+
enable_validation_group validation_group if validation_group
|
22
44
|
end
|
23
45
|
end
|
24
46
|
end
|
@@ -17,7 +17,7 @@ module HatTrick
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def initialize_copy(source)
|
20
|
-
@callbacks =
|
20
|
+
@callbacks = {}
|
21
21
|
@buttons = source.buttons.dup
|
22
22
|
@skipped = false
|
23
23
|
@repeat_of = source
|
@@ -74,27 +74,27 @@ module HatTrick
|
|
74
74
|
@include_data_key = hash.keys.first
|
75
75
|
end
|
76
76
|
|
77
|
-
def run_before_callback(context,
|
78
|
-
run_callback(:before, context,
|
77
|
+
def run_before_callback(context, model)
|
78
|
+
run_callback(:before, context, model)
|
79
79
|
end
|
80
80
|
|
81
|
-
def run_include_data_callback(context,
|
82
|
-
run_callback(:include_data, context,
|
81
|
+
def run_include_data_callback(context, model)
|
82
|
+
run_callback(:include_data, context, model)
|
83
83
|
end
|
84
84
|
|
85
|
-
def run_after_callback(context,
|
86
|
-
run_callback(:after, context,
|
85
|
+
def run_after_callback(context, model)
|
86
|
+
run_callback(:after, context, model)
|
87
87
|
end
|
88
88
|
|
89
89
|
protected
|
90
90
|
|
91
|
-
def run_callback(type, context,
|
91
|
+
def run_callback(type, context, model)
|
92
92
|
callback = callbacks[type.to_sym]
|
93
93
|
if callback && callback.is_a?(Proc)
|
94
|
-
if callback.arity >
|
95
|
-
|
96
|
-
|
97
|
-
|
94
|
+
if callback.arity > 0
|
95
|
+
unless model.is_a?(ActiveModel::Errors)
|
96
|
+
context.instance_exec model, &callback
|
97
|
+
end
|
98
98
|
else
|
99
99
|
context.instance_eval &callback
|
100
100
|
end
|
data/lib/hat_trick/version.rb
CHANGED
data/lib/hat_trick/wizard.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
require 'hat_trick/controller_hooks'
|
2
2
|
require 'hat_trick/wizard_steps'
|
3
|
+
require 'hat_trick/dsl'
|
3
4
|
|
4
5
|
module HatTrick
|
5
6
|
class Wizard
|
6
7
|
include WizardSteps
|
7
8
|
|
8
9
|
attr_accessor :controller, :model
|
9
|
-
attr_reader :current_step, :wizard_def, :
|
10
|
+
attr_reader :current_step, :wizard_def, :steps
|
10
11
|
|
11
12
|
def initialize(wizard_def)
|
12
13
|
@wizard_def = wizard_def
|
13
|
-
@wizard_dsl_context = DSL::WizardContext.new(@wizard_def)
|
14
|
-
@wizard_dsl_context.wizard = self
|
15
14
|
@steps = @wizard_def.steps.map { |s| HatTrick::Step.new(s, self) }
|
16
15
|
end
|
17
16
|
|
@@ -19,6 +18,13 @@ module HatTrick
|
|
19
18
|
@controller = new_controller
|
20
19
|
end
|
21
20
|
|
21
|
+
def model=(new_model)
|
22
|
+
@model = new_model
|
23
|
+
unless @model.class.included_modules.include?(HatTrick::ModelMethods)
|
24
|
+
@model.class.send(:include, HatTrick::ModelMethods)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
22
28
|
def current_step=(_step)
|
23
29
|
raise "Don't set current_step to nil" if _step.nil?
|
24
30
|
step = find_step(_step)
|
@@ -27,7 +33,11 @@ module HatTrick
|
|
27
33
|
end
|
28
34
|
|
29
35
|
def session
|
30
|
-
|
36
|
+
if controller.nil?
|
37
|
+
fake_session
|
38
|
+
else
|
39
|
+
controller.session
|
40
|
+
end
|
31
41
|
end
|
32
42
|
|
33
43
|
def model_created?
|
@@ -43,11 +53,13 @@ module HatTrick
|
|
43
53
|
end
|
44
54
|
|
45
55
|
def create_url
|
56
|
+
wizard_def.configured_create_url or
|
46
57
|
controller.url_for(:controller => controller.controller_name,
|
47
58
|
:action => 'create', :only_path => true)
|
48
59
|
end
|
49
60
|
|
50
61
|
def update_url
|
62
|
+
wizard_def.configured_update_url or
|
51
63
|
if model_created?
|
52
64
|
controller.url_for(:controller => controller.controller_name,
|
53
65
|
:action => 'update', :id => model,
|
@@ -80,28 +92,16 @@ module HatTrick
|
|
80
92
|
|
81
93
|
def start
|
82
94
|
session["hat-trick.steps_visited"] = []
|
83
|
-
self.current_step
|
95
|
+
self.current_step ||= first_step
|
84
96
|
run_before_callback
|
85
97
|
end
|
86
98
|
|
87
|
-
def finish
|
88
|
-
# Do something here
|
89
|
-
# Such as: Force the wizard to display the "done" page
|
90
|
-
Rails.logger.info "WIZARD FINISHED!"
|
91
|
-
end
|
92
|
-
|
93
99
|
def run_before_callback(step=current_step)
|
94
|
-
step.run_before_callback(controller,
|
100
|
+
step.run_before_callback(controller, model)
|
95
101
|
end
|
96
102
|
|
97
103
|
def run_after_callback(step=current_step)
|
98
|
-
step.run_after_callback(controller,
|
99
|
-
end
|
100
|
-
|
101
|
-
def advance_step_with_debugger
|
102
|
-
require 'ruby-debug'
|
103
|
-
debugger
|
104
|
-
advance_step
|
104
|
+
step.run_after_callback(controller, model)
|
105
105
|
end
|
106
106
|
|
107
107
|
def advance_step(next_step_name=nil)
|
@@ -114,7 +114,7 @@ module HatTrick
|
|
114
114
|
|
115
115
|
# finish if we're on the last step
|
116
116
|
if current_step == last_step && !requested_next_step
|
117
|
-
|
117
|
+
raise "Tried to advance beyond the last step of the wizard"
|
118
118
|
else # we're not on the last step
|
119
119
|
if requested_next_step
|
120
120
|
Rails.logger.info "Force advancing to step: #{requested_next_step}"
|
@@ -135,10 +135,20 @@ module HatTrick
|
|
135
135
|
end
|
136
136
|
|
137
137
|
def include_data
|
138
|
-
return {}
|
139
|
-
inc_data =
|
140
|
-
|
141
|
-
|
138
|
+
return {} if model.nil?
|
139
|
+
inc_data = {}
|
140
|
+
include_data_steps = steps_before(current_step) << current_step
|
141
|
+
include_data_steps.each do |step|
|
142
|
+
step_data = step.run_include_data_callback(controller, model)
|
143
|
+
next if step_data.nil? || !step_data.respond_to?(:as_json)
|
144
|
+
step_key = step.include_data_key.to_s.camelize(:lower)
|
145
|
+
begin
|
146
|
+
inc_data[step_key] = camelize_hash_keys(step_data)
|
147
|
+
rescue NoMethodError => e
|
148
|
+
Rails.logger.error "Unable to serialize data for step #{step}: #{e}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
inc_data
|
142
152
|
end
|
143
153
|
|
144
154
|
def alias_action_methods
|
@@ -155,6 +165,10 @@ module HatTrick
|
|
155
165
|
|
156
166
|
private
|
157
167
|
|
168
|
+
def fake_session
|
169
|
+
@fake_session ||= {}
|
170
|
+
end
|
171
|
+
|
158
172
|
def find_next_step
|
159
173
|
find_step(current_step.next_step) or find_step_after(current_step)
|
160
174
|
end
|
@@ -165,10 +179,13 @@ module HatTrick
|
|
165
179
|
end
|
166
180
|
|
167
181
|
def camelize_hash_keys(_hash)
|
168
|
-
return nil if _hash.nil?
|
169
182
|
hash = {}
|
170
|
-
_hash.each
|
171
|
-
|
183
|
+
if _hash.respond_to?(:each)
|
184
|
+
_hash.each do |k,v|
|
185
|
+
hash[k.to_s.camelize(:lower)] = v
|
186
|
+
end
|
187
|
+
else
|
188
|
+
hash = _hash
|
172
189
|
end
|
173
190
|
hash
|
174
191
|
end
|
@@ -26,7 +26,9 @@ module HatTrick
|
|
26
26
|
def steps_after(_step)
|
27
27
|
step = find_step(_step)
|
28
28
|
return [] unless step
|
29
|
-
|
29
|
+
step_index = steps.index(step)
|
30
|
+
max_index = steps.count - 1
|
31
|
+
after_index = step_index < max_index ? step_index + 1 : step_index
|
30
32
|
steps[after_index .. -1]
|
31
33
|
end
|
32
34
|
|
@@ -37,7 +39,8 @@ module HatTrick
|
|
37
39
|
def steps_before(_step)
|
38
40
|
step = find_step(_step)
|
39
41
|
return [] unless step
|
40
|
-
|
42
|
+
step_index = steps.index(step)
|
43
|
+
before_index = step_index > 0 ? step_index - 1 : step_index
|
41
44
|
steps[0 .. before_index]
|
42
45
|
end
|
43
46
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# will automatically get HatTrick::DSL included
|
4
|
+
class FakeController < ActionController::Base; end
|
5
|
+
|
6
|
+
describe HatTrick::DSL do
|
7
|
+
let(:controller_class) { FakeController }
|
8
|
+
|
9
|
+
# save some typing
|
10
|
+
def dsl(&block)
|
11
|
+
controller_class.instance_eval &block
|
12
|
+
end
|
13
|
+
|
14
|
+
describe HatTrick::DSL::ClassMethods do
|
15
|
+
describe "#step" do
|
16
|
+
it "should call Wizard#add_step" do
|
17
|
+
HatTrick::WizardDefinition.any_instance.expects(:add_step).with(:foo, {})
|
18
|
+
dsl do
|
19
|
+
wizard do
|
20
|
+
step :foo
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|