jeffp-wizardly 0.1.7 → 0.1.8
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.
data/README.rdoc
CHANGED
@@ -117,17 +117,66 @@ for both cases
|
|
117
117
|
act_wizardly_for :user, :redirect=>'/main'
|
118
118
|
end
|
119
119
|
|
120
|
-
====
|
120
|
+
==== Options For act_wizardly_for
|
121
121
|
|
122
122
|
Here's a list of options you can use in the macro
|
123
123
|
|
124
124
|
:completed => '/main/finished'
|
125
125
|
:canceled => {:controller=>'main', :action=>'canceled'}
|
126
126
|
:skip => true
|
127
|
+
:guard => false
|
127
128
|
:mask_fields => [:password, :password_confirmation] (by default)
|
129
|
+
:persist_model => {:once|:per_page}
|
130
|
+
:form_data => {:sandbox|:session}
|
128
131
|
|
129
132
|
Setting the :skip option to +true+ tells the scaffold helpers to include or exclude a skip button on each page.
|
130
133
|
The :mask_fields options tells the scaffold generator which fields to generate as 'type=password' fields.
|
134
|
+
:persist_model and :form_data are explained below.
|
135
|
+
|
136
|
+
|
137
|
+
==== Preserving Form Field Data
|
138
|
+
|
139
|
+
The :form_data option controls how the form data is preserved between
|
140
|
+
page requests that call outside the wizard controller. The default option setting,
|
141
|
+
:session, keeps the form data until the wizard is complete regardless of
|
142
|
+
whether the user leaves the wizard and returns later. The form
|
143
|
+
data is preserved for the life of the session or until the user completes the wizard.
|
144
|
+
|
145
|
+
The other option setting, :sandbox, clears the form data whenever
|
146
|
+
the user leaves the wizard before the wizard is complete. This includes pressing
|
147
|
+
a :cancel button, a hyperlink or plainly navigating somewhere else.
|
148
|
+
Upon returning to the wizard, the form is reset and the user starts fresh.
|
149
|
+
|
150
|
+
The form data is always cleared once the user has completed the wizard and the
|
151
|
+
database record has been created.
|
152
|
+
|
153
|
+
==== Guarding Wizard Entry
|
154
|
+
|
155
|
+
The :guard option controls how a user may enter the wizard. If set to true, the
|
156
|
+
default, the wizard is guarded from entry anywhere except the first page. The wizard
|
157
|
+
controller will automatically redirect to the first page. When set to false, entry
|
158
|
+
may occur at any point. This may be useful for testing purposes and instances where
|
159
|
+
the application needs to navigate away and return to the wizard.
|
160
|
+
|
161
|
+
The guarding behavior works a little differently depending on the :form_data setting.
|
162
|
+
When :form_data is set to :session (the default behavior), guarding only occurs
|
163
|
+
for the initial entry. Once a user has entered the form and started it, while
|
164
|
+
form data is being kept, the application may thereafter enter anywhere. On the
|
165
|
+
contrary, if :form_data is set to :sandbox, entry is always guarded, and once the user
|
166
|
+
leaves the wizard, entry may only occur at the initial page (as the form data has
|
167
|
+
been reset).
|
168
|
+
|
169
|
+
==== Saving The Model
|
170
|
+
|
171
|
+
The :persist_model option controls how the model is saved, either :once or :per_page.
|
172
|
+
The default option :once, only saves the model when the wizard is completed, by the
|
173
|
+
user pressing a :finish button or :next button on the final page. This method
|
174
|
+
prevents numerous incomplete models and possibly invalid models being saved to the
|
175
|
+
database.
|
176
|
+
|
177
|
+
The other option setting, :per_page, saves the model incrementally for each time
|
178
|
+
the form data validates as the user moves through the pages.
|
179
|
+
|
131
180
|
|
132
181
|
=== Buttons
|
133
182
|
|
@@ -263,6 +312,24 @@ call back for this.
|
|
263
312
|
end
|
264
313
|
end
|
265
314
|
|
315
|
+
=== Creating Scaffolds
|
316
|
+
|
317
|
+
Wizard scaffolds can be created for any wizardly controller (one using the acts_wizardly_for
|
318
|
+
macro).
|
319
|
+
|
320
|
+
./script/generate wizardly_scaffold controller_name --haml
|
321
|
+
|
322
|
+
The wizardly_scaffold generator will create HTML view scaffolds by default. Append a
|
323
|
+
--haml option to create scaffolds in HAML.
|
324
|
+
|
325
|
+
Sometimes you have already edited views from a scaffold but want to regenerate the
|
326
|
+
scaffold because of changes to your model without overwriting the current views.
|
327
|
+
Use the --underscore option to create corresponding views with an underscore prefixing
|
328
|
+
each page.
|
329
|
+
|
330
|
+
./script/generate wizardly_scaffold controller_name --underscore
|
331
|
+
|
332
|
+
|
266
333
|
== Advanced Configuration
|
267
334
|
|
268
335
|
To be provided
|
@@ -8,14 +8,20 @@ module Wizardly
|
|
8
8
|
module Wizard
|
9
9
|
class Configuration
|
10
10
|
attr_reader :pages, :completed_redirect, :canceled_redirect, :controller_name, :page_order
|
11
|
+
|
12
|
+
#enum_attr :persistance, %w(sandbox session database)
|
11
13
|
|
12
14
|
def initialize(controller_name, opts) #completed_redirect = nil, canceled_redirect = nil)
|
13
15
|
@controller_name = controller_name
|
14
16
|
@completed_redirect = opts[:redirect] || opts[:completed] || opts[:when_completed] #format_redirect(completed_redirect)
|
15
17
|
@canceled_redirect = opts[:redirect] || opts[:canceled] || opts[:when_canceled]
|
16
18
|
@allow_skipping = opts[:skip] || opts[:allow_skip] || opts[:allow_skipping] || false
|
17
|
-
@guard_entry = opts.key?(:guard) ? opts[:guard] : true
|
19
|
+
@guard_entry = opts.key?(:guard) ? opts[:guard] : true
|
18
20
|
@password_fields = opts[:mask_fields] || opts[:mask_passwords] || [:password, :password_confirmation]
|
21
|
+
@persist_model = opts[:persist_model] || :once
|
22
|
+
@form_data = opts[:form_data] || :session
|
23
|
+
raise(ArgumentError, ":persist_model option must be one of :once or :per_page", caller) unless [:once, :per_page].include?(@persist_model)
|
24
|
+
raise(ArgumentError, ":form_data option must be one of :sandbox or :session", caller) unless [:sandbox, :session].include?(@form_data)
|
19
25
|
@page_order = []
|
20
26
|
@pages = {}
|
21
27
|
@buttons = nil
|
@@ -25,6 +31,8 @@ module Wizardly
|
|
25
31
|
end
|
26
32
|
end
|
27
33
|
|
34
|
+
def persist_model_per_page?; @persist_model == :per_page; end
|
35
|
+
def form_data_keep_in_session?; @form_data == :session; end
|
28
36
|
def model; @wizard_model_sym; end
|
29
37
|
def model_instance_variable; "@#{@wizard_model_sym.to_s}"; end
|
30
38
|
def model_class_name; @wizard_model_class_name; end
|
@@ -37,6 +45,11 @@ module Wizardly
|
|
37
45
|
index += 1 unless self.last_page?(name)
|
38
46
|
@page_order[index]
|
39
47
|
end
|
48
|
+
def previous_page(name)
|
49
|
+
index = @page_order.index(name)
|
50
|
+
index -= 1 unless self.first_page?(name)
|
51
|
+
@page_order[index]
|
52
|
+
end
|
40
53
|
def button_for_function(name); @default_buttons[name]; end
|
41
54
|
def buttons
|
42
55
|
return @buttons if @buttons
|
@@ -49,9 +49,14 @@ MACRO
|
|
49
49
|
def index
|
50
50
|
redirect_to :action=>:#{self.page_order.first}
|
51
51
|
end
|
52
|
+
|
52
53
|
INDEX
|
53
54
|
mb.string
|
54
55
|
end
|
56
|
+
|
57
|
+
def persist_key;
|
58
|
+
@persist_key ||= "wizardly_#{controller_name.to_s.underscore}_#{model}".to_sym
|
59
|
+
end
|
55
60
|
|
56
61
|
def print_page_action_method(id)
|
57
62
|
page = @pages[id]
|
@@ -64,8 +69,8 @@ MACRO
|
|
64
69
|
@wizard = wizard_config
|
65
70
|
@title = '#{page.title}'
|
66
71
|
@description = '#{page.description}'
|
67
|
-
h = (
|
68
|
-
@#{self.model} =
|
72
|
+
h = (self.wizard_form_data||{}).merge(params[:#{self.model}] || {})
|
73
|
+
@#{self.model} = build_wizard_model(h)
|
69
74
|
if request.post? && callback_performs_action?(:on_post_#{id}_form)
|
70
75
|
raise CallbackError, "render or redirect not allowed in :on_post_#{id}_form callback", caller
|
71
76
|
end
|
@@ -87,31 +92,33 @@ MACRO
|
|
87
92
|
ONE
|
88
93
|
if self.last_page?(id)
|
89
94
|
mb << <<-TWO
|
90
|
-
|
95
|
+
callback_performs_action?(:on_#{id}_form_#{finish_button})
|
91
96
|
_on_wizard_#{finish_button}
|
92
97
|
redirect_to #{Utils.formatted_redirect(self.completed_redirect)} unless self.performed?
|
93
98
|
TWO
|
94
99
|
elsif self.first_page?(id)
|
95
100
|
mb << <<-THREE
|
96
101
|
if button_id == :#{finish_button}
|
97
|
-
|
102
|
+
callback_performs_action?(:on_#{id}_form_#{finish_button})
|
98
103
|
_on_wizard_#{finish_button} if button_id == :#{finish_button}
|
99
104
|
redirect_to #{Utils.formatted_redirect(self.completed_redirect)} unless self.performed?
|
100
105
|
return
|
101
106
|
end
|
102
|
-
|
107
|
+
save_wizard_model! if wizard_config.persist_model_per_page?
|
108
|
+
# session[:progression] = [:#{id}]
|
103
109
|
return if callback_performs_action?(:on_#{id}_form_#{next_button})
|
104
110
|
redirect_to :action=>:#{self.next_page(id)}
|
105
111
|
THREE
|
106
112
|
else
|
107
113
|
mb << <<-FOUR
|
108
114
|
if button_id == :#{finish_button}
|
109
|
-
|
115
|
+
callback_performs_action?(:on_#{id}_form_#{finish_button})
|
110
116
|
_on_wizard_#{finish_button} if button_id == :#{finish_button}
|
111
117
|
redirect_to #{Utils.formatted_redirect(self.completed_redirect)} unless self.performed?
|
112
118
|
return
|
113
119
|
end
|
114
|
-
|
120
|
+
save_wizard_model! if wizard_config.persist_model_per_page?
|
121
|
+
# session[:progression].push(:#{id})
|
115
122
|
return if callback_performs_action?(:on_#{id}_form_#{next_button})
|
116
123
|
redirect_to :action=>:#{self.next_page(id)}
|
117
124
|
FOUR
|
@@ -119,7 +126,7 @@ MACRO
|
|
119
126
|
|
120
127
|
mb << <<-ENSURE
|
121
128
|
ensure
|
122
|
-
|
129
|
+
self.wizard_form_data = h.merge(@#{self.model}.attributes) if (@#{self.model} && !@completed)
|
123
130
|
end
|
124
131
|
end
|
125
132
|
ENSURE
|
@@ -135,6 +142,8 @@ ENSURE
|
|
135
142
|
protected
|
136
143
|
def _on_wizard_#{finish}
|
137
144
|
@#{self.model}.save_without_validation!
|
145
|
+
@completed = true
|
146
|
+
reset_wizard_form_data
|
138
147
|
_wizard_final_redirect_to(:completed)
|
139
148
|
end
|
140
149
|
def _on_wizard_#{skip}
|
@@ -142,13 +151,13 @@ ENSURE
|
|
142
151
|
end
|
143
152
|
def _on_wizard_#{back}
|
144
153
|
# TODO: fix progression management
|
145
|
-
redirect_to(:action=>((session[:progression]||[]).pop || :#{self.page_order.first})) unless self.performed?
|
154
|
+
# redirect_to(:action=>((session[:progression]||[]).pop || :#{self.page_order.first})) unless self.performed?
|
155
|
+
redirect_to(:action=>wizard_config.previous_page(@step)) unless self.performed?
|
146
156
|
end
|
147
157
|
def _on_wizard_#{cancel}
|
148
158
|
_wizard_final_redirect_to(:canceled)
|
149
159
|
end
|
150
160
|
def _wizard_final_redirect_to(which_redirect)
|
151
|
-
flash.discard(:wizard_model)
|
152
161
|
initial_referer = reset_wizard_session_vars
|
153
162
|
unless self.performed?
|
154
163
|
redir = (which_redirect == :completed ? wizard_config.completed_redirect : wizard_config.canceled_redirect) || initial_referer
|
@@ -175,12 +184,53 @@ ENSURE
|
|
175
184
|
else
|
176
185
|
session[:initial_referer] = nil
|
177
186
|
end
|
178
|
-
|
187
|
+
if wizard_config.form_data_keep_in_session?
|
188
|
+
return if self.wizard_form_data # if it has an id we've started a wizard
|
189
|
+
else
|
190
|
+
reset_wizard_form_data
|
191
|
+
end
|
179
192
|
#{guard_line}
|
180
193
|
redirect_to :action=>:#{first_page} unless (params[:action] || '') == '#{first_page}'
|
181
|
-
end
|
194
|
+
end
|
182
195
|
hide_action :guard_entry
|
183
196
|
|
197
|
+
def save_wizard_model!
|
198
|
+
@#{self.model}.save_without_validation!
|
199
|
+
if wizard_config.form_data_keep_in_session?
|
200
|
+
h = self.wizard_form_data
|
201
|
+
h['id'] = @#{self.model}.id
|
202
|
+
self.wizard_form_data= h
|
203
|
+
end
|
204
|
+
end
|
205
|
+
def build_wizard_model(params)
|
206
|
+
if (wizard_config.persist_model_per_page? && (model_id = params['id']))
|
207
|
+
_model = #{self.model_class_name}.find(model_id)
|
208
|
+
_model.attributes = params
|
209
|
+
_model
|
210
|
+
else
|
211
|
+
#{self.model_class_name}.new(params)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
hide_action :build_wizard_model, :save_wizard_model!
|
215
|
+
|
216
|
+
def wizard_form_data=(hash)
|
217
|
+
if wizard_config.form_data_keep_in_session?
|
218
|
+
session[:#{self.persist_key}] = hash
|
219
|
+
else
|
220
|
+
if hash
|
221
|
+
flash[:#{self.persist_key}] = hash
|
222
|
+
else
|
223
|
+
flash.discard(:#{self.persist_key})
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def reset_wizard_form_data; self.wizard_form_data = nil; end
|
229
|
+
def wizard_form_data
|
230
|
+
wizard_config.form_data_keep_in_session? ? session[:#{self.persist_key}] : flash[:#{self.persist_key}]
|
231
|
+
end
|
232
|
+
hide_action :wizard_form_data, :wizard_form_data=, :reset_wizard_form_data
|
233
|
+
|
184
234
|
def render_wizard_form
|
185
235
|
end
|
186
236
|
hide_action :render_wizard_form
|
@@ -16,6 +16,7 @@ class WizardlyScaffoldGenerator < Rails::Generator::Base
|
|
16
16
|
def add_options!(opt)
|
17
17
|
opt.on('--haml', 'Generate scaffold for haml wizard') { |v| options[:output] = :haml }
|
18
18
|
opt.on('--ajax', 'Generate scaffold for ajax wizard') { |v| options[:output] = :ajax }
|
19
|
+
opt.on('--underscore', 'Append an underscore to front of each file') { |v| options[:underscore] = true }
|
19
20
|
end
|
20
21
|
|
21
22
|
|
@@ -62,10 +63,11 @@ class WizardlyScaffoldGenerator < Rails::Generator::Base
|
|
62
63
|
#m.directory(File.join('test/functional', controller_class_path))
|
63
64
|
#m.directory(File.join('public/stylesheets', class_path))
|
64
65
|
|
66
|
+
underscore = options[:underscore] ? '_' : ''
|
65
67
|
pages.each do |id, page|
|
66
68
|
m.template(
|
67
69
|
"form.#{view_file_ext.first}",
|
68
|
-
File.join('app/views', controller_class_path, controller_name, "#{id}.#{view_file_ext.last}"),
|
70
|
+
File.join('app/views', controller_class_path, controller_name, "#{underscore}#{id}.#{view_file_ext.last}"),
|
69
71
|
:assigns=>{:id=>id, :page=>page}
|
70
72
|
)
|
71
73
|
end
|
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.
|
4
|
+
version: 0.1.8
|
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-
|
12
|
+
date: 2009-08-12 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|