acts_as_multipart_form 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3 -0
- data/Gemfile +27 -0
- data/Gemfile.lock +157 -0
- data/LICENSE.txt +20 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +65 -0
- data/VERSION +1 -0
- data/acts_as_multipart_form.gemspec +163 -0
- data/app/controllers/multipart_form/in_progress_forms_controller.rb +0 -0
- data/app/models/multipart_form/in_progress_form.rb +20 -0
- data/app/views/multipart_form/_breadcrumb.html.erb +21 -0
- data/app/views/multipart_form/_index_links.html.erb +20 -0
- data/app/views/multipart_form/in_progress_form/index.html.erb +0 -0
- data/app/views/multipart_form/in_progress_form/index.html.haml +0 -0
- data/lib/acts_as_multipart_form.rb +2 -0
- data/lib/acts_as_multipart_form/config.rb +36 -0
- data/lib/acts_as_multipart_form/engine.rb +4 -0
- data/lib/acts_as_multipart_form/multipart_form_in_controller.rb +301 -0
- data/lib/acts_as_multipart_form/multipart_form_in_model.rb +105 -0
- data/lib/acts_as_multipart_form/railtie.rb +14 -0
- data/lib/generators/acts_as_multipart_form/install_generator.rb +44 -0
- data/lib/generators/acts_as_multipart_form/templates/config.rb +6 -0
- data/lib/generators/acts_as_multipart_form/templates/migrations/install_migration.rb.erb +17 -0
- data/spec/acts_as_multipart_form_spec.rb +7 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/people_controller.rb +53 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/person.rb +5 -0
- data/spec/dummy/app/models/person_with_multiple_actsas.rb +5 -0
- data/spec/dummy/app/models/person_with_multiple_forms.rb +4 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/people/_job_info.html.erb +8 -0
- data/spec/dummy/app/views/people/_person_info.html.erb +8 -0
- data/spec/dummy/app/views/people/hire_form.html.erb +10 -0
- data/spec/dummy/app/views/people/index.html.erb +16 -0
- data/spec/dummy/app/views/people/show.html.erb +0 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +45 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +22 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +26 -0
- data/spec/dummy/config/environments/production.rb +49 -0
- data/spec/dummy/config/environments/test.rb +35 -0
- data/spec/dummy/config/initializers/acts_as_multipart_form.rb +6 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +66 -0
- data/spec/dummy/db/migrate/20110715180834_create_people.rb +13 -0
- data/spec/dummy/db/migrate/20110722130249_create_multipart_form_tables.rb +17 -0
- data/spec/dummy/db/schema.rb +31 -0
- data/spec/dummy/features/form_breadcrumb.feature +75 -0
- data/spec/dummy/features/form_submission.feature +23 -0
- data/spec/dummy/features/index_links.feature +56 -0
- data/spec/dummy/features/step_definitions/acts_as_multipart_form_steps.rb +30 -0
- data/spec/dummy/features/step_definitions/config_steps.rb +23 -0
- data/spec/dummy/features/step_definitions/web_steps.rb +214 -0
- data/spec/dummy/features/support/env.rb +15 -0
- data/spec/dummy/features/support/paths.rb +31 -0
- data/spec/dummy/features/support/selectors.rb +39 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/javascripts/application.js +2 -0
- data/spec/dummy/public/javascripts/controls.js +965 -0
- data/spec/dummy/public/javascripts/dragdrop.js +974 -0
- data/spec/dummy/public/javascripts/effects.js +1123 -0
- data/spec/dummy/public/javascripts/prototype.js +6001 -0
- data/spec/dummy/public/javascripts/rails.js +191 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/in_progress_form_spec.rb +43 -0
- data/spec/integration/navigation_spec.rb +9 -0
- data/spec/multipart_form_in_controller_integeration_spec.rb +23 -0
- data/spec/multipart_form_in_controller_spec.rb +360 -0
- data/spec/multipart_form_in_model_integration_spec.rb +30 -0
- data/spec/multipart_form_in_model_spec.rb +156 -0
- data/spec/spec_helper.rb +38 -0
- metadata +296 -0
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module MultipartForm
|
2
|
+
# Stores information about multipart forms in progress
|
3
|
+
# Useful when displaying information about the form especially when a user
|
4
|
+
# stops halfway through a form and comes back to it
|
5
|
+
#
|
6
|
+
# form_subject is a polymorphic relationship to the model that uses the form
|
7
|
+
#
|
8
|
+
# form_name relates to the name of the form on the model on the line
|
9
|
+
# acts_as_multipart_form :form_name => {:type => ...
|
10
|
+
# @author Jeremiah Hemphill
|
11
|
+
class InProgressForm < ::ActiveRecord::Base
|
12
|
+
set_table_name "multipart_form_in_progress_forms"
|
13
|
+
belongs_to :form_subject, :polymorphic => true
|
14
|
+
|
15
|
+
validates_presence_of :form_subject
|
16
|
+
validates_presence_of :form_name
|
17
|
+
validates_presence_of :last_completed_step
|
18
|
+
validates_inclusion_of :completed, :in => [true, false]
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<div class='multipart_form_breadcrumb'>
|
2
|
+
<% if ActsAsMultipartForm.config.show_previous_next_links %>
|
3
|
+
<div class='multipart_form_breadcrumb_previous'>
|
4
|
+
<%= link_to "Previous", send(@multipart_form_path, :id => @form_subject.id, :multipart_form_part => @previous_multipart_form_part ) %>
|
5
|
+
</div>
|
6
|
+
<% end %>
|
7
|
+
<div class='multipart_form_breadcrumb_parts'>
|
8
|
+
<% @available_multipart_form_parts.each do |part| %>
|
9
|
+
<% if part[:name].to_s != @multipart_form_part.to_s %>
|
10
|
+
<%= link_to part[:name].to_s.titleize, send(@multipart_form_path, :id => @form_subject.id, :multipart_form_part => part[:name]) %>
|
11
|
+
<% else %>
|
12
|
+
<%= part[:name].to_s.titleize %>
|
13
|
+
<% end %>
|
14
|
+
<% end %>
|
15
|
+
</div>
|
16
|
+
<% if ActsAsMultipartForm.config.show_previous_next_links %>
|
17
|
+
<div class='multipart_form_breadcrumb_next'>
|
18
|
+
<%= link_to "Next", send(@multipart_form_path, :id => @form_subject.id, :multipart_form_part => @next_multipart_form_part ) %>
|
19
|
+
</div>
|
20
|
+
<% end %>
|
21
|
+
</div>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<div class='multipart_form_index_links'>
|
2
|
+
<div class='multipart_form_index_links_links'>
|
3
|
+
<% @multipart_form_index_parts[locals[:form_subject].id][:parts].each do |part| %>
|
4
|
+
<% if ActsAsMultipartForm.config.use_numbered_parts_on_index %>
|
5
|
+
<%= link_to part[:number].to_s, send(@multipart_form_path, :id => locals[:form_subject].id, :multipart_form_part => part[:name]) %>
|
6
|
+
<% else %>
|
7
|
+
<%= link_to part[:name].to_s.titleize, send(@multipart_form_path, :id => locals[:form_subject].id, :multipart_form_part => part[:name]) %>
|
8
|
+
<% end %>
|
9
|
+
<% end %>
|
10
|
+
</div>
|
11
|
+
<% if ActsAsMultipartForm.config.show_completed %>
|
12
|
+
<div class='multipart_form_index_links_complete'>
|
13
|
+
<% if @multipart_form_index_parts[locals[:form_subject].id][:completed] %>
|
14
|
+
Complete
|
15
|
+
<% else %>
|
16
|
+
Incomplete
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
<% end %>
|
20
|
+
</div>
|
File without changes
|
File without changes
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# this file was stolen from kaminari
|
2
|
+
require 'active_support/configurable'
|
3
|
+
|
4
|
+
module ActsAsMultipartForm
|
5
|
+
|
6
|
+
# create new configs by passing a block with the config assignment
|
7
|
+
def self.configure(&block)
|
8
|
+
yield @config ||= ActsAsMultipartForm::Configuration.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.config
|
12
|
+
@config
|
13
|
+
end
|
14
|
+
|
15
|
+
# setup config data
|
16
|
+
class Configuration
|
17
|
+
include ActiveSupport::Configurable
|
18
|
+
config_accessor :show_completed
|
19
|
+
config_accessor :show_incomplete_parts
|
20
|
+
config_accessor :use_numbered_parts_on_index
|
21
|
+
config_accessor :show_previous_next_links
|
22
|
+
|
23
|
+
def param_name
|
24
|
+
config.param_name.respond_to?(:call) ? config.param_name.call() : config.param_name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# setup default options
|
29
|
+
# this should match the generator config that goes in the initializer file
|
30
|
+
configure do |config|
|
31
|
+
config.show_completed = true
|
32
|
+
config.show_incomplete_parts = false
|
33
|
+
config.use_numbered_parts_on_index = true
|
34
|
+
config.show_previous_next_links = true
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,301 @@
|
|
1
|
+
module ActsAsMultipartForm
|
2
|
+
|
3
|
+
# Specify this to let the controller know how to setup the multipart forms.
|
4
|
+
# This sets up the form action, the form parts, and any other needed options.
|
5
|
+
# Each controller can have multiple multipart forms included on it
|
6
|
+
#
|
7
|
+
# The controller expects there to be an action for every form part for form_part_name and form_part_name_update
|
8
|
+
# There are currently no checks to verify these actions but an exception will be thrown when a missing
|
9
|
+
# action is called
|
10
|
+
module MultipartFormInController
|
11
|
+
|
12
|
+
def self.included(base)
|
13
|
+
base.extend ClassMethods
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
# Sets up the multipart form handler with the data needed to create and move through a multipart form
|
18
|
+
# The arguments takes several important values including:
|
19
|
+
# name: The name of the multipart form. This creates a controller action with that name that can be used in routes and other situations
|
20
|
+
# parts: An array of multipart form parts. Each part must have a corresponding part_name and part_name_update method
|
21
|
+
# model: The name of the model used to identify the multipart form. Defaults to the singularized name of the controller.
|
22
|
+
# form_route: The route for the form as specified in the config/routes file. Defaults to model_form_name downcased.
|
23
|
+
# show_route: The route the form redirects to once the last part is filled out. Defaults to the name of the model, downcased.
|
24
|
+
#
|
25
|
+
# The args parameter is an array of hashes and multiple multipart forms can be specified with a single acts_as_multipart_form call.
|
26
|
+
# To keep the lines from being too long, acts_as_multipart_form can be called multiple times to setup the forms
|
27
|
+
#
|
28
|
+
# sample set of multipart form actions
|
29
|
+
# def person_info
|
30
|
+
# @person = Person.find(params[:id])
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# def person_info_update
|
34
|
+
# @person = Person.find(params[:id])
|
35
|
+
# @person = Person.new if @person.nil?
|
36
|
+
#
|
37
|
+
# valid = @person.update_attributes(params[:person])
|
38
|
+
# return {:valid => valid, :errors => @person.errors}
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# def job_info
|
42
|
+
# @job_position = JobPosition.new
|
43
|
+
# @job_position.person = Person.find(load_multipart_form_data(form_instance_id, :person))
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# def job_info_update
|
47
|
+
# valid = @job_position.update_attributes(params[:job_position])
|
48
|
+
# return {:valid => valid, :errors => @job_position.errors}
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# @param [Array] args An array of hashes that determines the data for a multipart form
|
52
|
+
def acts_as_multipart_form(*args)
|
53
|
+
|
54
|
+
mattr_accessor :multipart_forms unless self.respond_to?(:multipart_forms)
|
55
|
+
self.multipart_forms = {} unless self.multipart_forms.is_a?(Hash)
|
56
|
+
|
57
|
+
forms = []
|
58
|
+
args.each do |arg|
|
59
|
+
# add the update parts
|
60
|
+
parts = arg[:parts]
|
61
|
+
arg[:parts] = []
|
62
|
+
parts.each do |part|
|
63
|
+
arg[:parts] << part
|
64
|
+
arg[:parts] << (part.to_s + "_update").to_sym
|
65
|
+
end
|
66
|
+
# sets default model if it is not set
|
67
|
+
arg[:model] = self.to_s.gsub("Controller", "").singularize unless arg.has_key?(:model)
|
68
|
+
arg[:form_route] = (arg[:model].downcase + "_" + arg[:name].to_s) unless arg.has_key?(:form_route)
|
69
|
+
arg[:show_route] = (arg[:model].downcase) unless arg.has_key?(:show_route)
|
70
|
+
# copy args to fields
|
71
|
+
self.multipart_forms[arg[:name]] = arg
|
72
|
+
forms << arg[:name]
|
73
|
+
end
|
74
|
+
|
75
|
+
before_filter :multipart_form_handler, :only => forms
|
76
|
+
|
77
|
+
include ActsAsMultipartForm::MultipartFormInController::InstanceMethods
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
module InstanceMethods
|
83
|
+
|
84
|
+
# A bad hack to load the multipart form information for the index page
|
85
|
+
# This must be called if you want to use the multipart_form/index_links partial
|
86
|
+
#
|
87
|
+
# Adds several instance variables available for the view
|
88
|
+
#
|
89
|
+
# @param [Symbol] form_name The name of the form
|
90
|
+
# @param [Array] form_subjects An array of active record objects that are form subjects for the given form
|
91
|
+
def load_multipart_form_index_links(form_name, form_subjects)
|
92
|
+
@multipart_form_index_parts = {}
|
93
|
+
form_subjects.each do |form_subject|
|
94
|
+
in_progress_form = find_or_create_multipart_in_progress_form(form_name, form_subject)
|
95
|
+
@multipart_form_index_parts[form_subject.id] = {}
|
96
|
+
@multipart_form_index_parts[form_subject.id][:parts] = get_available_multipart_form_parts(form_name, in_progress_form.last_completed_step)
|
97
|
+
@multipart_form_index_parts[form_subject.id][:completed] = in_progress_form.completed
|
98
|
+
end
|
99
|
+
@multipart_form_path = (self.multipart_forms[form_name][:form_route] + "_path").to_sym
|
100
|
+
end
|
101
|
+
|
102
|
+
# Handles multipart form setup on the controller
|
103
|
+
# Automatically called on the hire form action as a before filter
|
104
|
+
#
|
105
|
+
# It adds a bunch of instance variables to the controller so they are accessible to the view page.
|
106
|
+
# Not sure if this is the best way to do things
|
107
|
+
def multipart_form_handler
|
108
|
+
form_name = params[:action].to_sym
|
109
|
+
form_subject_id = params[:id]
|
110
|
+
|
111
|
+
form_subject = find_or_create_multipart_form_subject(form_name, form_subject_id)
|
112
|
+
params[:id] = form_subject.id
|
113
|
+
|
114
|
+
in_progress_form = find_or_create_multipart_in_progress_form(form_name, form_subject)
|
115
|
+
|
116
|
+
# set the part based on the params or in progress form
|
117
|
+
if params[:multipart_form_part]
|
118
|
+
part = params[:multipart_form_part].to_sym
|
119
|
+
elsif in_progress_form.last_completed_step != "none"
|
120
|
+
part = get_next_multipart_form_part(form_name, in_progress_form.last_completed_step.to_sym)
|
121
|
+
else
|
122
|
+
part = self.multipart_forms[form_name][:parts].first
|
123
|
+
end
|
124
|
+
|
125
|
+
# call and save the part information
|
126
|
+
if(part && self.multipart_forms[form_name][:parts].include?(part.to_sym))
|
127
|
+
result = self.send(part)
|
128
|
+
|
129
|
+
if(part.match(/_update$/))
|
130
|
+
if(result && result[:valid])
|
131
|
+
completed = redirect_to_next_multipart_form_part(form_name, form_subject, part)
|
132
|
+
in_progress_form.update_attributes(:last_completed_step => part, :completed => completed)
|
133
|
+
else
|
134
|
+
# render the previous page but stay on this page so we keep the errors
|
135
|
+
part = get_previous_multipart_form_part(form_name, part)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
# get two previous parts so the previous link works
|
139
|
+
previous_part = get_previous_multipart_form_part(form_name, part)
|
140
|
+
@previous_multipart_form_part = get_previous_multipart_form_part(form_name, previous_part).to_s
|
141
|
+
# needs to be a string so that the view can read it
|
142
|
+
@multipart_form_part = part.to_s
|
143
|
+
@next_multipart_form_part = get_next_multipart_form_part(form_name, part).to_s
|
144
|
+
@form_subject = form_subject
|
145
|
+
@available_multipart_form_parts = get_available_multipart_form_parts(form_name, in_progress_form.last_completed_step)
|
146
|
+
@multipart_form_path = (self.multipart_forms[form_name][:form_route] + "_path").to_sym
|
147
|
+
@multipart_form_complete = in_progress_form.completed
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Determines if the symbol matches a multipart form name
|
152
|
+
#
|
153
|
+
# @param [Symbol] sym A name that may or may not correspond to a multipart form name
|
154
|
+
# @return [Boolean] Returns true if the symbol matches a multipart form name
|
155
|
+
def multipart_form_action?(sym)
|
156
|
+
self.multipart_forms.keys.include?(sym)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Gets the next multipart form part for the form or returns the current part if it is first
|
160
|
+
#
|
161
|
+
# @param [Symbol] form The name of the multipart form
|
162
|
+
# @param [Symbol] part The name of the current part
|
163
|
+
# @returns [Symbol] The name of the next part
|
164
|
+
def get_previous_multipart_form_part(form, part)
|
165
|
+
part_index = self.multipart_forms[form][:parts].index(part)
|
166
|
+
if part_index > 0
|
167
|
+
return self.multipart_forms[form][:parts][part_index - 1]
|
168
|
+
else
|
169
|
+
return part
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Gets the previous multipart form part for the form or returns the current part if it is first
|
174
|
+
#
|
175
|
+
# @param [Symbol] form The name of the multipart form
|
176
|
+
# @param [Symbol] part The name of the current part
|
177
|
+
# @returns [Symbol] The name of the previous part
|
178
|
+
def get_next_multipart_form_part(form, part)
|
179
|
+
part_index = self.multipart_forms[form][:parts].index(part)
|
180
|
+
if part_index < self.multipart_forms[form][:parts].length - 1
|
181
|
+
return self.multipart_forms[form][:parts][part_index + 1]
|
182
|
+
else
|
183
|
+
return part
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Determines if the given multipart form part is the last part of the form
|
188
|
+
#
|
189
|
+
# @param [Symbol] form The name of the multipart form
|
190
|
+
# @param [Symbol] part The name o the current part
|
191
|
+
# @returns [Boolean] True if the given part matches the last part
|
192
|
+
def last_multipart_form_part?(form, part)
|
193
|
+
self.multipart_forms[form][:parts].last == part
|
194
|
+
end
|
195
|
+
|
196
|
+
# Determines if the given multipart form part is the first part of the form
|
197
|
+
#
|
198
|
+
# @param [Symbol] form The name of the multipart form
|
199
|
+
# @param [Symbol] part The name o the current part
|
200
|
+
# @returns [Boolean] True if the given part matches the first part
|
201
|
+
def first_multipart_form_part?(form, part)
|
202
|
+
self.multipart_forms[form][:parts].first == part
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
# Given a form name and a form subject id, it creates the form subject
|
207
|
+
# The form subject is defined by the id and the multipart form's model attribute
|
208
|
+
# The subject is created with values and saved without validations (this might change in the future)
|
209
|
+
#
|
210
|
+
# @param [Symbol] form_name The name of the multipart form
|
211
|
+
# @param [Integer] form_dubject_id The id of the form subject (could be nil)
|
212
|
+
# @return [FormSubject] The form subject object based on the multipart form's model or nil if the id is set and not found
|
213
|
+
def find_or_create_multipart_form_subject(form_name, form_subject_id)
|
214
|
+
# find or create the form subject
|
215
|
+
model = self.multipart_forms[form_name][:model]
|
216
|
+
if form_subject_id
|
217
|
+
form_subject = model.constantize.find(form_subject_id)
|
218
|
+
else
|
219
|
+
form_subject = model.constantize.new()
|
220
|
+
form_subject.save(:validate => false)
|
221
|
+
end
|
222
|
+
return form_subject
|
223
|
+
end
|
224
|
+
|
225
|
+
# Returns the InProgressForm object when given the form name and subject
|
226
|
+
# Creates the InPorgressForm object if it doesn't exist for the given form name/form subject pair
|
227
|
+
#
|
228
|
+
# @param [Symbol] form_name The name of the multipart form
|
229
|
+
# @param [FormSubject] form_subject The multipart form's subject
|
230
|
+
# @returns [InProgressForm] The associated or new in progress form object
|
231
|
+
def find_or_create_multipart_in_progress_form(form_name, form_subject)
|
232
|
+
# find or create the in progress form
|
233
|
+
# not sure why the polymorphic relationship isn't working here
|
234
|
+
in_progress_form = MultipartForm::InProgressForm.where(
|
235
|
+
:form_subject_id => form_subject.id,
|
236
|
+
:form_subject_type => form_subject.class.to_s,
|
237
|
+
:form_name => form_name).first
|
238
|
+
if !in_progress_form
|
239
|
+
in_progress_form = MultipartForm::InProgressForm.create(
|
240
|
+
:form_subject_id => form_subject.id,
|
241
|
+
:form_subject_type => form_subject.class.to_s,
|
242
|
+
:form_name => form_name,
|
243
|
+
:last_completed_step => "none",
|
244
|
+
:completed => false)
|
245
|
+
end
|
246
|
+
return in_progress_form
|
247
|
+
end
|
248
|
+
|
249
|
+
# Adds a redirect based on the information passed in.
|
250
|
+
# If on the last part of the form, tries to redirect to the view page,
|
251
|
+
# otherwise to the next form part.
|
252
|
+
#
|
253
|
+
# This method needs signficantly more testing (7-20-2011)
|
254
|
+
#
|
255
|
+
# @param [Sybmol] form_name The name of the form
|
256
|
+
# @param [FormSubject] form_subject The subject of the form
|
257
|
+
# @param [Symbol] part The current form part
|
258
|
+
def redirect_to_next_multipart_form_part(form_name, form_subject, part)
|
259
|
+
# set highest completed part to the current part4
|
260
|
+
if(last_multipart_form_part?(form_name, part))
|
261
|
+
# render the view page(not sure how to do this)
|
262
|
+
redirect_to( send(self.multipart_forms[form_name][:show_route] + "_path", form_subject) )
|
263
|
+
completed = true
|
264
|
+
else
|
265
|
+
# render the next page
|
266
|
+
next_part = get_next_multipart_form_part(form_name, part)
|
267
|
+
# maybe pass in a route
|
268
|
+
redirect_to ( send(
|
269
|
+
self.multipart_forms[form_name][:form_route] + "_path",
|
270
|
+
:id => form_subject.id.to_s,
|
271
|
+
:multipart_form_part => next_part.to_s))
|
272
|
+
completed = false
|
273
|
+
end
|
274
|
+
return completed
|
275
|
+
end
|
276
|
+
|
277
|
+
# Gets the multipart form parts the user is allowed to directly link to
|
278
|
+
# with respect to the config information.
|
279
|
+
#
|
280
|
+
# If the config option show_incomplete_parts is set to false, do not return parts past the in_progress_form's last completed step
|
281
|
+
#
|
282
|
+
# @param [Symbol] form_name The name of the form
|
283
|
+
# @returns [Array] An array of form part symbols with no _update parts and other config restrictions
|
284
|
+
def get_available_multipart_form_parts(form_name, last_completed_part)
|
285
|
+
add_parts = true
|
286
|
+
parts = []
|
287
|
+
# loop over the parts
|
288
|
+
self.multipart_forms[form_name][:parts].each do |part|
|
289
|
+
if( add_parts && !part.match(/_update$/) )
|
290
|
+
parts << { :name => part, :number => parts.length + 1 }
|
291
|
+
end
|
292
|
+
if !ActsAsMultipartForm.config.show_incomplete_parts && part.to_s == last_completed_part.to_s
|
293
|
+
add_parts = false
|
294
|
+
end
|
295
|
+
end
|
296
|
+
return parts
|
297
|
+
end
|
298
|
+
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module ActsAsMultipartForm
|
2
|
+
# Specify this to let the model know to expect multipart_form controller actions
|
3
|
+
# Allows the model to run conditional validations by giving access to methods
|
4
|
+
# with the form: multipart_form_name_multipart_controller_action.
|
5
|
+
#
|
6
|
+
# It includes support for multiple forms on a single controller by passing in an array of
|
7
|
+
# form symbols or a single symbol.
|
8
|
+
module MultipartFormInModel
|
9
|
+
|
10
|
+
def self.included(base)
|
11
|
+
base.extend ClassMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
# Adds the information to the model needed to do conditional validations on the multipart forms
|
16
|
+
# Creates the multipart_forms field to store the list of forms the model has access to
|
17
|
+
# Creates the multipart_form_controller_action field to store the form the controller is currently on
|
18
|
+
# This is used for validations among other things
|
19
|
+
#
|
20
|
+
# @param [Hash] options A hash of symbols that represent multipart forms in the controller
|
21
|
+
def multipart_formable(*args)
|
22
|
+
|
23
|
+
mattr_accessor :multipart_form_controller_action unless self.respond_to?(:multipart_form_controller_action)
|
24
|
+
mattr_accessor :multipart_forms unless self.respond_to?(:multipart_forms)
|
25
|
+
self.multipart_forms = [] unless self.multipart_forms.is_a?(Array)
|
26
|
+
self.multipart_forms |= args[0][:forms]
|
27
|
+
|
28
|
+
# after save, the current controller action should not be set
|
29
|
+
after_save :reset_multipart_form_controller_action
|
30
|
+
|
31
|
+
include ActsAsMultipartForm::MultipartFormInModel::InstanceMethods
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module InstanceMethods
|
36
|
+
|
37
|
+
# Sets the controller action to nil
|
38
|
+
# When we are not performing a save (or other action from a controller),
|
39
|
+
# the controller action should not be set
|
40
|
+
def reset_multipart_form_controller_action
|
41
|
+
self.multipart_form_controller_action = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
# Determines whether multipart form controller is in use
|
45
|
+
# @returns [Boolean] True if both the multipart_forms and multipart_form_controller fields are set
|
46
|
+
def using_multipart_forms?
|
47
|
+
return(!self.multipart_forms.nil? && !self.multipart_form_controller_action.nil?)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Overrides method missing to return true if the method is of the form
|
51
|
+
# multipart_form_name_multipart_controller_action
|
52
|
+
#
|
53
|
+
# If those conditions are not satisfied, called super
|
54
|
+
#
|
55
|
+
# @param [Symbol] sym The name of the method
|
56
|
+
# @param [Array[ args The arguments of the method
|
57
|
+
# @returns [Boolean] Whether or not the argument corresponds to a multipart form, otherwise super
|
58
|
+
def method_missing(sym, *args)
|
59
|
+
if multipart_form_method?(sym)
|
60
|
+
return multipart_form_controller_action?(sym)
|
61
|
+
else
|
62
|
+
super
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Overrides respond to to return true if the method is of the form
|
67
|
+
# multipart_form_name_multipart_controller_action
|
68
|
+
#
|
69
|
+
# If those conditions are not satisfied, called super
|
70
|
+
#
|
71
|
+
# @param [Symbol] sym The name of the method
|
72
|
+
# @param [Array[ args The arguments of the method
|
73
|
+
# @returns [Boolean] Whether or not the argument corresponds to a multipart form, otherwise super
|
74
|
+
def respond_to?(sym, *args)
|
75
|
+
if multipart_form_method?(sym)
|
76
|
+
return multipart_form_controller_action?(sym)
|
77
|
+
else
|
78
|
+
super
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# determines whether the given method should be handled by the multipart form method handler
|
83
|
+
# based on whether it starts with the form name followed by an underscore
|
84
|
+
#
|
85
|
+
# @param [Symbol] sym Method to check
|
86
|
+
# @return [Boolean] Whether or not the symbol starts with one of the multipart forms
|
87
|
+
def multipart_form_method?(sym)
|
88
|
+
if self.multipart_forms
|
89
|
+
return self.multipart_forms.select {|form| sym.to_s =~ /^#{form}_/}.length > 0
|
90
|
+
end
|
91
|
+
return false
|
92
|
+
end
|
93
|
+
|
94
|
+
# Determines if the symbol corresponds to a multipart form action
|
95
|
+
# @param [Symbol] sym The name of the method
|
96
|
+
# @returns [Boolean] Whether or not the argument corresponds to a multipart form, otherwise super
|
97
|
+
def multipart_form_controller_action?(sym)
|
98
|
+
if using_multipart_forms?
|
99
|
+
return self.multipart_forms.select {|form| form.to_s + "_" + self.multipart_form_controller_action + "?" == sym.to_s}.length > 0
|
100
|
+
end
|
101
|
+
return false
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|