jeffp-wizardly 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
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
|
|