acts_as_multipart_form 0.0.1
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/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
|