wizardly 0.1.8.9
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +33 -0
- data/LICENSE +20 -0
- data/README.rdoc +645 -0
- data/init.rb +1 -0
- data/lib/jeffp-wizardly.rb +1 -0
- data/lib/validation_group.rb +147 -0
- data/lib/wizardly.rb +31 -0
- data/lib/wizardly/action_controller.rb +36 -0
- data/lib/wizardly/wizard.rb +16 -0
- data/lib/wizardly/wizard/button.rb +35 -0
- data/lib/wizardly/wizard/configuration.rb +194 -0
- data/lib/wizardly/wizard/configuration/methods.rb +422 -0
- data/lib/wizardly/wizard/dsl.rb +27 -0
- data/lib/wizardly/wizard/page.rb +62 -0
- data/lib/wizardly/wizard/text_helpers.rb +16 -0
- data/lib/wizardly/wizard/utils.rb +11 -0
- data/rails_generators/wizardly_app/USAGE +6 -0
- data/rails_generators/wizardly_app/templates/wizardly.rake +37 -0
- data/rails_generators/wizardly_app/wizardly_app_generator.rb +41 -0
- data/rails_generators/wizardly_controller/USAGE +3 -0
- data/rails_generators/wizardly_controller/templates/controller.rb.erb +34 -0
- data/rails_generators/wizardly_controller/templates/helper.rb.erb +14 -0
- data/rails_generators/wizardly_controller/wizardly_controller_generator.rb +57 -0
- data/rails_generators/wizardly_scaffold/USAGE +4 -0
- data/rails_generators/wizardly_scaffold/templates/form.html.erb +23 -0
- data/rails_generators/wizardly_scaffold/templates/form.html.haml.erb +22 -0
- data/rails_generators/wizardly_scaffold/templates/helper.rb.erb +30 -0
- data/rails_generators/wizardly_scaffold/templates/images/back.png +0 -0
- data/rails_generators/wizardly_scaffold/templates/images/cancel.png +0 -0
- data/rails_generators/wizardly_scaffold/templates/images/finish.png +0 -0
- data/rails_generators/wizardly_scaffold/templates/images/next.png +0 -0
- data/rails_generators/wizardly_scaffold/templates/images/skip.png +0 -0
- data/rails_generators/wizardly_scaffold/templates/layout.html.erb +15 -0
- data/rails_generators/wizardly_scaffold/templates/layout.html.haml.erb +10 -0
- data/rails_generators/wizardly_scaffold/templates/style.css +54 -0
- data/rails_generators/wizardly_scaffold/wizardly_scaffold_generator.rb +109 -0
- metadata +90 -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
|
data/lib/wizardly.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'validation_group'
|
2
|
+
require 'wizardly/action_controller'
|
3
|
+
|
4
|
+
module Wizardly
|
5
|
+
module ActionController
|
6
|
+
module MacroMethods
|
7
|
+
def wizard_for_model(model, opts={}, &block)
|
8
|
+
include Wizardly::ActionController
|
9
|
+
#check for validation group gem
|
10
|
+
configure_wizard_for_model(model, opts, &block)
|
11
|
+
end
|
12
|
+
alias_method :act_wizardly_for, :wizard_for_model
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
begin
|
18
|
+
ActiveRecord::Base.class_eval do
|
19
|
+
class << self
|
20
|
+
alias_method :wizardly_page, :validation_group
|
21
|
+
end
|
22
|
+
end
|
23
|
+
rescue
|
24
|
+
end
|
25
|
+
|
26
|
+
ActionController::Base.send(:extend, Wizardly::ActionController::MacroMethods)
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
@@ -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,16 @@
|
|
1
|
+
require 'wizardly/wizard/configuration'
|
2
|
+
|
3
|
+
module Wizardly
|
4
|
+
class WizardlyError < StandardError; end
|
5
|
+
class ModelNotFoundError < WizardlyError; end
|
6
|
+
class ValidationGroupError < WizardlyError; end
|
7
|
+
class CallbackError < WizardlyError; end
|
8
|
+
class MissingCallbackError < WizardlyError; end
|
9
|
+
class WizardConfigurationError < WizardlyError; end
|
10
|
+
class RedirectNotDefinedError < WizardlyError; end
|
11
|
+
|
12
|
+
class WizardlyGeneratorError < WizardlyError; end
|
13
|
+
class WizardlyScaffoldError < WizardlyGeneratorError; end
|
14
|
+
class WizardlyControllerGeneratorError < WizardlyGeneratorError; end
|
15
|
+
|
16
|
+
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,194 @@
|
|
1
|
+
require 'wizardly/wizard/utils'
|
2
|
+
require 'wizardly/wizard/dsl'
|
3
|
+
require 'wizardly/wizard/button'
|
4
|
+
require 'wizardly/wizard/page'
|
5
|
+
require 'wizardly/wizard/configuration/methods'
|
6
|
+
|
7
|
+
module Wizardly
|
8
|
+
module Wizard
|
9
|
+
class Configuration
|
10
|
+
include TextHelpers
|
11
|
+
attr_reader :pages, :completed_redirect, :canceled_redirect, :controller_path, :controller_class_name, :controller_name, :page_order
|
12
|
+
|
13
|
+
#enum_attr :persistance, %w(sandbox session database)
|
14
|
+
|
15
|
+
def initialize(controller, opts) #completed_redirect = nil, canceled_redirect = nil)
|
16
|
+
@controller_class_name = controller.to_s.camelcase
|
17
|
+
@controller_class_name += 'Controller' unless @controller_class_name =~ /Controller$/
|
18
|
+
@controller_path = @controller_class_name.sub(/Controller$/,'').underscore
|
19
|
+
@controller_name = @controller_class_name.demodulize.sub(/Controller$/,'').underscore
|
20
|
+
@completed_redirect = opts[:completed] || opts[:when_completed] || opts[:redirect] #format_redirect(completed_redirect)
|
21
|
+
@canceled_redirect = opts[:canceled] || opts[:when_canceled] || opts[:redirect]
|
22
|
+
@include_skip_button = opts[:skip] || opts[:allow_skip] || opts[:allow_skipping] || false
|
23
|
+
@include_cancel_button = opts.key?(:cancel) ? opts[:cancel] : true
|
24
|
+
@guard_entry = opts.key?(:guard) ? opts[:guard] : true
|
25
|
+
@password_fields = opts[:mask_fields] || opts[:mask_passwords] || [:password, :password_confirmation]
|
26
|
+
@persist_model = opts[:persist_model] || :per_page
|
27
|
+
@form_data = opts[:form_data] || :session
|
28
|
+
raise(ArgumentError, ":persist_model option must be one of :once or :per_page", caller) unless [:once, :per_page].include?(@persist_model)
|
29
|
+
raise(ArgumentError, ":form_data option must be one of :sandbox or :session", caller) unless [:sandbox, :session].include?(@form_data)
|
30
|
+
@page_order = []
|
31
|
+
@pages = {}
|
32
|
+
@buttons = nil
|
33
|
+
@default_buttons = Hash[*[:next, :back, :cancel, :finish, :skip].collect {|default| [default, Button.new(default)] }.flatten]
|
34
|
+
end
|
35
|
+
|
36
|
+
def guard?; @guard_entry; end
|
37
|
+
def persist_model_per_page?; @persist_model == :per_page; end
|
38
|
+
def form_data_keep_in_session?; @form_data == :session; end
|
39
|
+
def model; @wizard_model_sym; end
|
40
|
+
def model_instance_variable; "@#{@wizard_model_sym.to_s}"; end
|
41
|
+
def model_class_name; @wizard_model_class_name; end
|
42
|
+
def model_const; @wizard_model_const; end
|
43
|
+
|
44
|
+
def first_page?(name); @page_order.first == name; end
|
45
|
+
def last_page?(name); @page_order.last == name; end
|
46
|
+
def next_page(name)
|
47
|
+
index = @page_order.index(name)
|
48
|
+
index += 1 unless self.last_page?(name)
|
49
|
+
@page_order[index]
|
50
|
+
end
|
51
|
+
def previous_page(name)
|
52
|
+
index = @page_order.index(name)
|
53
|
+
index -= 1 unless self.first_page?(name)
|
54
|
+
@page_order[index]
|
55
|
+
end
|
56
|
+
def button_for_function(name); @default_buttons[name]; end
|
57
|
+
def buttons
|
58
|
+
return @buttons if @buttons
|
59
|
+
# reduce buttons
|
60
|
+
@buttons = Hash[*@default_buttons.collect{|k,v|[v.id, v]}.flatten]
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.create(controller_name, model_name, opts={}, &block)
|
64
|
+
# controller_name = controller_name.to_s.underscore.sub(/_controller$/, '').to_sym
|
65
|
+
model_name = model_name.to_s.underscore.to_sym
|
66
|
+
config = Wizardly::Wizard::Configuration.new(controller_name, opts)
|
67
|
+
config.inspect_model!(model_name)
|
68
|
+
Wizardly::Wizard::DSL.new(config).instance_eval(&block) if block_given?
|
69
|
+
config
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def inspect_model!(model)
|
74
|
+
# first examine the model symbol, transform and see if the constant
|
75
|
+
# exists
|
76
|
+
begin
|
77
|
+
@wizard_model_sym = model.to_sym
|
78
|
+
@wizard_model_class_name = model.to_s.camelize
|
79
|
+
@wizard_model_const = @wizard_model_class_name.constantize
|
80
|
+
rescue Exception=>e
|
81
|
+
raise ModelNotFoundError, "Cannot convert :#{@wizard_model_sym} to model constant for #{@wizard_model_class_name}: " + e.message, caller
|
82
|
+
end
|
83
|
+
|
84
|
+
begin
|
85
|
+
@page_order = @wizard_model_const.validation_group_order
|
86
|
+
rescue Exception => e
|
87
|
+
raise ValidationGroupError, "Unable to read validation groups from #{@wizard_model_class_name}: " + e.message, caller
|
88
|
+
end
|
89
|
+
raise(ValidationGroupError, "No validation groups defined for model #{@wizard_model_class_name}", caller) unless (@page_order && !@page_order.empty?)
|
90
|
+
|
91
|
+
begin
|
92
|
+
groups = @wizard_model_const.validation_groups
|
93
|
+
enum_attrs = @wizard_model_const.respond_to?(:enumerated_attributes) ? @wizard_model_const.enumerated_attributes.collect {|k,v| k } : []
|
94
|
+
model_inst = @wizard_model_const.new
|
95
|
+
last_index = @page_order.size-1
|
96
|
+
@page_order.each_with_index do |p, index|
|
97
|
+
fields = groups[p].map do |f|
|
98
|
+
column = model_inst.column_for_attribute(f)
|
99
|
+
type = case
|
100
|
+
when enum_attrs.include?(f) then :enum
|
101
|
+
when (@password_fields && @password_fields.include?(f)) then :password
|
102
|
+
else
|
103
|
+
column ? column.type : :string
|
104
|
+
end
|
105
|
+
PageField.new(f, type)
|
106
|
+
end
|
107
|
+
page = Page.new(self, p, fields)
|
108
|
+
|
109
|
+
# default button settings based on order, can be altered by
|
110
|
+
# set_page(@id).buttons_to []
|
111
|
+
buttons = []
|
112
|
+
buttons << @default_buttons[:next] unless index >= last_index
|
113
|
+
buttons << @default_buttons[:finish] if index == last_index
|
114
|
+
buttons << @default_buttons[:back] unless index == 0
|
115
|
+
buttons << @default_buttons[:skip] if (@include_skip_button && index != last_index)
|
116
|
+
buttons << @default_buttons[:cancel] if (@include_cancel_button)
|
117
|
+
page.buttons = buttons
|
118
|
+
@pages[page.id] = page
|
119
|
+
end
|
120
|
+
rescue Exception => e
|
121
|
+
raise ValidationGroupError, "Failed to configure wizard from #{@wizard_model_class_name} validation groups: " + e.message, caller
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
public
|
126
|
+
# internal DSL method handlers
|
127
|
+
def _when_completed_redirect_to(redir); @completed_redirect = redir; end
|
128
|
+
def _when_canceled_redirect_to(redir); @canceled_redirect = redir; end
|
129
|
+
def _change_button(name)
|
130
|
+
raise(WizardConfigurationError, "Button :#{name} in _change_button() call does not exist", caller) unless self.buttons.key?(name)
|
131
|
+
_buttons = self.buttons
|
132
|
+
@buttons = nil # clear the buttons for regeneration after change in next line
|
133
|
+
_buttons[name]
|
134
|
+
end
|
135
|
+
def _create_button(name, opts)
|
136
|
+
id = opts[:id] || button_name_to_symbol(name)
|
137
|
+
raise(WizardConfigurationError, "Button '#{name}' with id :#{id} cannot be created. The ID already exists.", caller) if self.buttons.key?(id)
|
138
|
+
@buttons=nil
|
139
|
+
@default_buttons[id] = UserDefinedButton.new(id, name)
|
140
|
+
end
|
141
|
+
def _set_page(name); @pages[name]; end
|
142
|
+
def _mask_passwords(passwords)
|
143
|
+
case passwords
|
144
|
+
when String
|
145
|
+
passwords = [passwords.to_sym]
|
146
|
+
when Symbol
|
147
|
+
passwords = [passwords]
|
148
|
+
when Array
|
149
|
+
else
|
150
|
+
raise(WizardlyConfigurationError, "mask_passwords method only accepts string, symbol or array of password fields")
|
151
|
+
end
|
152
|
+
@password_fields.push(*passwords).uniq!
|
153
|
+
end
|
154
|
+
|
155
|
+
def print_config
|
156
|
+
io = StringIO.new
|
157
|
+
class_name = controller_name.to_s.camelize
|
158
|
+
class_name += 'Controller' unless class_name =~ /Controller$/
|
159
|
+
io.puts "#{class_name} wizard configuration"
|
160
|
+
io.puts
|
161
|
+
io.puts "model: #{model_class_name}"
|
162
|
+
io.puts "instance: @#{model}"
|
163
|
+
io.puts
|
164
|
+
io.puts "pages:"
|
165
|
+
self.page_order.each do |pid|
|
166
|
+
page = pages[pid]
|
167
|
+
# io.puts " #{index+1}. '#{page.title}' page (:#{page.id}) has"
|
168
|
+
io.puts " '#{page.title}' page (:#{page.id}) has"
|
169
|
+
io.puts " --fields: #{page.fields.inject([]){|a, f| a << '"'+f.name.to_s.titleize+'" [:'+f.column_type.to_s+']'}.join(', ')}"
|
170
|
+
io.puts " --buttons: #{page.buttons.inject([]){|a, b| a << b.name.to_s }.join(', ')}"
|
171
|
+
end
|
172
|
+
io.puts
|
173
|
+
io.puts "redirects:"
|
174
|
+
io.puts " when completed: #{completed_redirect ? completed_redirect.inspect : 'redirects to initial referer by default (specify :completed=>url to override)'}"
|
175
|
+
io.puts " when canceled: #{canceled_redirect ? canceled_redirect.inspect : 'redirects to initial referer by default (specify :canceled=>url to override)'}"
|
176
|
+
io.puts
|
177
|
+
io.puts "buttons:"
|
178
|
+
self.buttons.each do |k, b|
|
179
|
+
bs = StringIO.new
|
180
|
+
bs << " #{b.name} (:#{b.id}) "
|
181
|
+
if (b.user_defined?)
|
182
|
+
bs << "-- user defined button and function"
|
183
|
+
else
|
184
|
+
dk = @default_buttons.index(b)
|
185
|
+
bs << "-- used for internal <#{dk}> functionality"
|
186
|
+
end
|
187
|
+
io.puts bs.string
|
188
|
+
end
|
189
|
+
io.puts
|
190
|
+
io.string
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|