surveyor 0.22.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +83 -0
- data/Gemfile.rails_version +7 -1
- data/README.md +114 -16
- data/Rakefile +15 -9
- data/app/inputs/quiet_input.rb +5 -0
- data/app/inputs/surveyor_check_boxes_input.rb +35 -0
- data/app/inputs/surveyor_radio_input.rb +18 -0
- data/app/views/partials/_answer.html.haml +4 -4
- data/app/views/partials/_question.html.haml +7 -7
- data/app/views/partials/_question_group.html.haml +9 -8
- data/app/views/surveyor/export.json.rabl +28 -25
- data/app/views/surveyor/new.html.haml +8 -5
- data/app/views/surveyor/show.json.rabl +3 -2
- data/ci-exec.sh +13 -7
- data/cucumber.yml +3 -3
- data/doc/REPRESENTATIONS.md +34 -0
- data/doc/api_id_schema.json +7 -0
- data/doc/response_set_schema.json +54 -0
- data/doc/surveyor question combinations.png +0 -0
- data/doc/surveyor_timestamp_schema.json +9 -0
- data/features/ajax_submissions.feature +140 -0
- data/features/export_to_json.feature +182 -34
- data/features/no_duplicates.feature +110 -0
- data/features/show_survey.feature +1 -1
- data/features/step_definitions/parser_steps.rb +25 -2
- data/features/step_definitions/surveyor_steps.rb +145 -20
- data/features/step_definitions/ui_steps.rb +3 -0
- data/features/support/database_cleaner.rb +16 -0
- data/features/support/env.rb +21 -17
- data/features/support/simultaneous_ajax.rb +101 -0
- data/features/support/single_quit_selenium_driver.rb +23 -0
- data/features/support/slow_updates.rb +18 -0
- data/features/surveyor.feature +174 -44
- data/features/surveyor_dependencies.feature +80 -39
- data/features/surveyor_parser.feature +114 -20
- data/features/z_redcap_parser.feature +0 -1
- data/lib/{generators/surveyor/templates/public → assets}/images/surveyor/next.gif +0 -0
- data/lib/{generators/surveyor/templates/public → assets}/images/surveyor/prev.gif +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/lib/assets/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-icons_ef8c08_256x240.png +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-icons_ffffff_256x240.png +0 -0
- data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery-ui-timepicker-addon.js +23 -23
- data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery-ui.js +125 -125
- data/lib/assets/javascripts/surveyor/jquery.selectToUISlider.js +240 -0
- data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery.surveyor.js +52 -57
- data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery.tools.min.js +7 -7
- data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/dateinput.css +13 -13
- data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/jquery-ui-timepicker-addon.css +0 -0
- data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/jquery-ui.custom.css +17 -17
- data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/reset.css +1 -1
- data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/results.css +0 -0
- data/lib/assets/stylesheets/surveyor/ui.slider.extras.css +110 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/sass → assets/stylesheets}/surveyor.sass +15 -7
- data/lib/generators/surveyor/custom_generator.rb +3 -2
- data/lib/generators/surveyor/install_generator.rb +59 -17
- data/lib/generators/surveyor/templates/app/assets/javascripts/surveyor_all.js +5 -0
- data/lib/generators/surveyor/templates/app/assets/stylesheets/surveyor_all.css +9 -0
- data/lib/generators/surveyor/templates/app/controllers/surveyor_controller.rb +2 -1
- data/lib/generators/surveyor/templates/app/views/layouts/surveyor_custom.html.erb +1 -0
- data/lib/generators/surveyor/templates/config/locales/surveyor_es.yml +1 -0
- data/lib/generators/surveyor/templates/config/locales/surveyor_he.yml +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_api_id_to_question_groups.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_api_ids.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_api_ids_to_response_sets_and_responses.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_correct_answer_id_to_questions.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_default_value_to_answers.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_display_order_to_surveys.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_display_type_to_answers.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_index_to_response_sets.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_index_to_surveys.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_section_id_to_responses.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_unique_index_on_access_code_and_version_in_surveys.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/add_unique_indicies.rb +3 -2
- data/lib/generators/surveyor/templates/db/migrate/add_version_to_surveys.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/api_ids_must_be_unique.rb +23 -0
- data/lib/generators/surveyor/templates/db/migrate/create_answers.rb +6 -5
- data/lib/generators/surveyor/templates/db/migrate/create_dependencies.rb +2 -1
- data/lib/generators/surveyor/templates/db/migrate/create_dependency_conditions.rb +2 -1
- data/lib/generators/surveyor/templates/db/migrate/create_question_groups.rb +5 -4
- data/lib/generators/surveyor/templates/db/migrate/create_questions.rb +4 -3
- data/lib/generators/surveyor/templates/db/migrate/create_response_sets.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/create_responses.rb +10 -9
- data/lib/generators/surveyor/templates/db/migrate/create_survey_sections.rb +5 -4
- data/lib/generators/surveyor/templates/db/migrate/create_surveys.rb +4 -3
- data/lib/generators/surveyor/templates/db/migrate/create_validation_conditions.rb +5 -4
- data/lib/generators/surveyor/templates/db/migrate/create_validations.rb +3 -2
- data/lib/generators/surveyor/templates/db/migrate/drop_unique_index_on_access_code_in_surveys.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/update_blank_api_ids_on_question_group.rb +22 -0
- data/lib/generators/surveyor/templates/db/migrate/update_blank_versions_on_surveys.rb +13 -0
- data/lib/generators/surveyor/templates/surveys/date_survey.rb +1 -0
- data/lib/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +54 -24
- data/lib/generators/surveyor/templates/surveys/quiz.rb +1 -0
- data/lib/generators/surveyor/templates/{public/stylesheets/sass → vendor/assets/stylesheets}/custom.sass +1 -1
- data/lib/surveyor/common.rb +16 -31
- data/lib/surveyor/engine.rb +2 -4
- data/lib/surveyor/helpers/asset_pipeline.rb +13 -0
- data/lib/surveyor/helpers/formtastic_custom_input.rb +17 -0
- data/lib/surveyor/helpers/surveyor_helper_methods.rb +10 -8
- data/lib/surveyor/models/answer_methods.rb +3 -0
- data/lib/surveyor/models/dependency_condition_methods.rb +27 -28
- data/lib/surveyor/models/dependency_methods.rb +3 -0
- data/lib/surveyor/models/question_group_methods.rb +3 -0
- data/lib/surveyor/models/question_methods.rb +10 -7
- data/lib/surveyor/models/response_methods.rb +16 -0
- data/lib/surveyor/models/response_set_methods.rb +71 -64
- data/lib/surveyor/models/survey_methods.rb +19 -28
- data/lib/surveyor/models/survey_section_methods.rb +3 -0
- data/lib/surveyor/models/validation_condition_methods.rb +4 -2
- data/lib/surveyor/models/validation_methods.rb +3 -0
- data/lib/surveyor/parser.rb +198 -148
- data/lib/surveyor/redcap_parser.rb +120 -80
- data/lib/surveyor/surveyor_controller_methods.rb +86 -37
- data/lib/surveyor/version.rb +2 -2
- data/lib/surveyor.rb +5 -6
- data/lib/tasks/surveyor_tasks.rake +19 -7
- data/spec/controllers/surveyor_controller_spec.rb +166 -92
- data/spec/factories.rb +33 -32
- data/spec/helpers/formtastic_custom_input_spec.rb +16 -0
- data/spec/lib/common_spec.rb +0 -39
- data/spec/lib/redcap_parser_spec.rb +24 -24
- data/spec/models/answer_spec.rb +12 -0
- data/spec/models/dependency_condition_spec.rb +279 -323
- data/spec/models/dependency_spec.rb +10 -0
- data/spec/models/question_group_spec.rb +12 -0
- data/spec/models/question_spec.rb +12 -0
- data/spec/models/response_set_spec.rb +189 -139
- data/spec/models/response_spec.rb +60 -0
- data/spec/models/survey_section_spec.rb +9 -0
- data/spec/models/survey_spec.rb +72 -9
- data/spec/models/validation_condition_spec.rb +9 -1
- data/spec/models/validation_spec.rb +10 -0
- data/spec/spec_helper.rb +25 -6
- data/surveyor.gemspec +5 -4
- metadata +332 -291
- data/features/step_definitions/common_steps.rb +0 -3
- data/lib/formtastic/surveyor_builder.rb +0 -82
- data/lib/generators/surveyor/templates/public/javascripts/surveyor/jquery.blockUI.js +0 -499
data/lib/surveyor/parser.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
%w(survey survey_section question_group question dependency dependency_condition answer validation validation_condition).each {|model| require model }
|
2
2
|
module Surveyor
|
3
|
+
class ParserError < StandardError; end
|
3
4
|
class Parser
|
4
5
|
class << self; attr_accessor :options end
|
5
|
-
|
6
|
+
|
6
7
|
# Attributes
|
7
8
|
attr_accessor :context
|
8
9
|
|
@@ -17,7 +18,7 @@ module Surveyor
|
|
17
18
|
self.options ||= {}
|
18
19
|
print str if self.options[:trace] == true
|
19
20
|
end
|
20
|
-
|
21
|
+
|
21
22
|
# Instance methods
|
22
23
|
def initialize
|
23
24
|
self.context = {}
|
@@ -30,27 +31,31 @@ module Surveyor
|
|
30
31
|
def method_missing(missing_method, *args, &block)
|
31
32
|
method_name, reference_identifier = missing_method.to_s.split("_", 2)
|
32
33
|
type = full(method_name)
|
33
|
-
|
34
|
+
|
34
35
|
Surveyor::Parser.rake_trace reference_identifier.blank? ? "#{type} " : "#{type}_#{reference_identifier} "
|
35
|
-
|
36
|
+
|
36
37
|
# check for blocks
|
37
|
-
raise "Error: A #{type.humanize} cannot be empty" if block_models.include?(type) && !block_given?
|
38
|
-
raise "Error: Dropping the #{type.humanize} block like it's hot!" if !block_models.include?(type) && block_given?
|
39
|
-
|
38
|
+
raise Surveyor::ParserError, "Error: A #{type.humanize} cannot be empty" if block_models.include?(type) && !block_given?
|
39
|
+
raise Surveyor::ParserError, "Error: Dropping the #{type.humanize} block like it's hot!" if !block_models.include?(type) && block_given?
|
40
|
+
|
40
41
|
# parse and build
|
41
|
-
type.classify.constantize.parse_and_build(context, args, method_name, reference_identifier)
|
42
|
-
|
42
|
+
type.classify.constantize.new.extend("SurveyorParser#{type.classify}Methods".constantize).parse_and_build(context, args, method_name, reference_identifier)
|
43
|
+
|
43
44
|
# evaluate and clear context for block models
|
44
45
|
if block_models.include?(type)
|
45
|
-
self.instance_eval(&block)
|
46
|
+
self.instance_eval(&block)
|
46
47
|
if type == 'survey'
|
48
|
+
resolve_dependency_condition_references
|
49
|
+
resolve_question_correct_answers
|
50
|
+
report_lost_and_duplicate_references
|
47
51
|
Surveyor::Parser.rake_trace "\n"
|
48
|
-
Surveyor::Parser.rake_trace context[
|
52
|
+
Surveyor::Parser.rake_trace context[:survey].save ? "saved. " : " not saved! #{context[type.to_sym].errors.each_full{|x| x }.join(", ")} "
|
53
|
+
else
|
54
|
+
context[type.to_sym].clear(context)
|
49
55
|
end
|
50
|
-
context[type.to_sym].clear(context) unless type == 'survey'
|
51
56
|
end
|
52
57
|
end
|
53
|
-
|
58
|
+
|
54
59
|
# Private methods
|
55
60
|
private
|
56
61
|
|
@@ -71,228 +76,273 @@ module Surveyor
|
|
71
76
|
def block_models
|
72
77
|
%w(survey survey_section question_group)
|
73
78
|
end
|
79
|
+
def report_lost_and_duplicate_references
|
80
|
+
raise Surveyor::ParserError, "Bad references: #{self.context[:bad_references].join("; ")}" unless self.context[:bad_references].empty?
|
81
|
+
raise Surveyor::ParserError, "Duplicate references: #{self.context[:duplicate_references].join("; ")}" unless self.context[:duplicate_references].empty?
|
82
|
+
end
|
83
|
+
def resolve_question_correct_answers
|
84
|
+
self.context[:questions_with_correct_answers].each do |question_reference_idenitifer, correct_answer_reference|
|
85
|
+
# Looking up references for quiz answers
|
86
|
+
if self.context[:answer_references][question_reference_idenitifer] &&
|
87
|
+
(a = self.context[:answer_references][question_reference_idenitifer][correct_answer_reference]) &&
|
88
|
+
a.save
|
89
|
+
self.context[:question_references][question_reference_idenitifer].correct_answer_id = a.id
|
90
|
+
else
|
91
|
+
self.context[:bad_references].push "q_#{question_reference_idenitifer}.correct => a_#{correct_answer_reference}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
def resolve_dependency_condition_references
|
96
|
+
self.context[:dependency_conditions].each do |dc|
|
97
|
+
# Looking up references to questions and answers for linking the dependency objects
|
98
|
+
self.context[:bad_references].push "q_#{dc.question_reference}" unless (dc.question = self.context[:question_references][dc.question_reference])
|
99
|
+
self.context[:answer_references][dc.question_reference] ||= {}
|
100
|
+
self.context[:bad_references].push "q_#{dc.question_reference}, a_#{dc.answer_reference}" if !dc.answer_reference.blank? and (dc.answer = self.context[:answer_references][dc.question_reference][dc.answer_reference]).nil?
|
101
|
+
end
|
102
|
+
end
|
74
103
|
end
|
75
104
|
end
|
76
105
|
|
77
106
|
# Surveyor models with extra parsing methods
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
def
|
107
|
+
|
108
|
+
# Survey model
|
109
|
+
module SurveyorParserSurveyMethods
|
110
|
+
def parse_and_build(context, args, original_method, reference_identifier)
|
82
111
|
# clear context
|
83
|
-
context
|
84
|
-
|
85
|
-
context[:answer_references] = {}
|
86
|
-
|
112
|
+
clear(context)
|
113
|
+
|
87
114
|
# build and set context
|
88
115
|
title = args[0]
|
89
|
-
|
90
|
-
|
116
|
+
self.attributes = ({
|
117
|
+
:title => title,
|
118
|
+
:reference_identifier => reference_identifier }.merge(args[1] || {}))
|
119
|
+
context[:survey] = self
|
91
120
|
end
|
92
121
|
def clear(context)
|
93
|
-
context.delete_if{|k,v| true
|
94
|
-
context
|
95
|
-
|
122
|
+
context.delete_if{|k,v| true}
|
123
|
+
context.merge!({
|
124
|
+
:question_references => {},
|
125
|
+
:answer_references => {},
|
126
|
+
:bad_references => [],
|
127
|
+
:duplicate_references => [],
|
128
|
+
:dependency_conditions => [],
|
129
|
+
:questions_with_correct_answers => {} })
|
96
130
|
end
|
97
131
|
end
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
def
|
132
|
+
|
133
|
+
# SurveySection model
|
134
|
+
module SurveyorParserSurveySectionMethods
|
135
|
+
def parse_and_build(context, args, original_method, reference_identifier)
|
102
136
|
# clear context
|
103
|
-
context
|
104
|
-
|
137
|
+
clear(context)
|
138
|
+
|
105
139
|
# build and set context
|
106
140
|
title = args[0]
|
107
|
-
|
108
|
-
|
141
|
+
self.attributes = ({
|
142
|
+
:title => title,
|
143
|
+
:display_order => context[:survey].sections.size }.merge(args[1] || {}))
|
144
|
+
context[:survey].sections << context[:survey_section] = self
|
109
145
|
end
|
110
146
|
def clear(context)
|
111
|
-
|
147
|
+
[ :survey_section,
|
148
|
+
:question_group,
|
149
|
+
:question,
|
150
|
+
:dependency,
|
151
|
+
:dependency_condition,
|
152
|
+
:answer,
|
153
|
+
:validation,
|
154
|
+
:validation_condition ].each{|k| context.delete k}
|
112
155
|
end
|
113
156
|
end
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
def
|
157
|
+
|
158
|
+
# QuestionGroup model
|
159
|
+
module SurveyorParserQuestionGroupMethods
|
160
|
+
def parse_and_build(context, args, original_method, reference_identifier)
|
118
161
|
# clear context
|
119
|
-
context
|
120
|
-
|
121
|
-
# build and set context
|
122
|
-
context[:question_group] = context[:question_group] = new({ :text => args[0] || "Question Group",
|
123
|
-
:display_type => (original_method =~ /grid|repeater/ ? original_method : "default")}.merge(args[1] || {}))
|
162
|
+
clear(context)
|
124
163
|
|
164
|
+
# build and set context
|
165
|
+
self.attributes = ({
|
166
|
+
:text => args[0] || "Question Group",
|
167
|
+
:display_type => (original_method =~ /grid|repeater/ ? original_method : "default")}.merge(args[1] || {}))
|
168
|
+
context[:question_group] = self
|
125
169
|
end
|
126
170
|
def clear(context)
|
127
|
-
|
171
|
+
[ :question_group,
|
172
|
+
:question,
|
173
|
+
:dependency,
|
174
|
+
:dependency_condition,
|
175
|
+
:answer,
|
176
|
+
:validation,
|
177
|
+
:validation_condition ].each{|k| context.delete k}
|
128
178
|
end
|
129
179
|
end
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
attr_accessor :correct, :context_reference
|
135
|
-
before_save :resolve_correct_answers
|
136
|
-
|
137
|
-
def self.parse_and_build(context, args, original_method, reference_identifier)
|
180
|
+
|
181
|
+
# Question model
|
182
|
+
module SurveyorParserQuestionMethods
|
183
|
+
def parse_and_build(context, args, original_method, reference_identifier)
|
138
184
|
# clear context
|
139
|
-
|
140
|
-
|
185
|
+
[ :question,
|
186
|
+
:dependency,
|
187
|
+
:dependency_condition,
|
188
|
+
:answer,
|
189
|
+
:validation,
|
190
|
+
:validation_condition ].each{|k| context.delete k}
|
191
|
+
|
141
192
|
# build and set context
|
142
193
|
text = args[0] || "Question"
|
143
|
-
|
144
|
-
|
194
|
+
hash_args = args[1] || {}
|
195
|
+
correct = hash_args.delete :correct
|
196
|
+
self.attributes = ({
|
145
197
|
:question_group => context[:question_group],
|
146
198
|
:reference_identifier => reference_identifier,
|
147
199
|
:text => text,
|
148
200
|
:display_type => (original_method =~ /label|image/ ? original_method : "default"),
|
149
|
-
:display_order => context[:survey_section].questions.size }.merge(
|
150
|
-
|
201
|
+
:display_order => context[:survey_section].questions.size }.merge(hash_args))
|
202
|
+
context[:survey_section].questions << context[:question] = self
|
203
|
+
|
204
|
+
# keep reference for correct answers
|
205
|
+
context[:questions_with_correct_answers][self.reference_identifier] = correct unless self.reference_identifier.blank? or correct.blank?
|
206
|
+
|
151
207
|
# keep reference for dependencies
|
152
|
-
|
153
|
-
|
208
|
+
unless self.reference_identifier.blank?
|
209
|
+
context[:duplicate_references].push "q_#{self.reference_identifier}" if context[:question_references].has_key?(self.reference_identifier)
|
210
|
+
context[:question_references][self.reference_identifier] = context[:question]
|
211
|
+
end
|
212
|
+
|
154
213
|
# add grid answers
|
155
214
|
if context[:question_group] && context[:question_group].display_type == "grid"
|
156
215
|
(context[:grid_answers] || []).each do |grid_answer|
|
157
|
-
a = context[:question].answers.build(grid_answer.attributes)
|
158
|
-
context[:answer_references][reference_identifier] ||= {} unless reference_identifier.blank?
|
159
|
-
context[:answer_references][reference_identifier][grid_answer.reference_identifier] = a unless reference_identifier.blank? or grid_answer.reference_identifier.blank?
|
216
|
+
a = context[:question].answers.build(grid_answer.attributes.reject{|k,v| %w(id api_id created_at updated_at).include?(k)})
|
217
|
+
context[:answer_references][self.reference_identifier] ||= {} unless self.reference_identifier.blank?
|
218
|
+
context[:answer_references][self.reference_identifier][grid_answer.reference_identifier] = a unless self.reference_identifier.blank? or grid_answer.reference_identifier.blank?
|
160
219
|
end
|
161
220
|
end
|
162
221
|
end
|
163
|
-
|
164
|
-
def resolve_correct_answers
|
165
|
-
unless correct.blank? or reference_identifier.blank? or context_reference.blank?
|
166
|
-
# Looking up references for quiz answers
|
167
|
-
context_reference[:answer_references][reference_identifier] ||= {}
|
168
|
-
Surveyor::Parser.rake_trace( (self.correct_answer = context_reference[:answer_references][reference_identifier][correct]) ? "found correct answer:#{correct} " : "lost! correct answer:#{correct} ")
|
169
|
-
end
|
170
|
-
end
|
171
222
|
end
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
def
|
223
|
+
|
224
|
+
# Dependency model
|
225
|
+
module SurveyorParserDependencyMethods
|
226
|
+
def parse_and_build(context, args, original_method, reference_identifier)
|
176
227
|
# clear context
|
177
|
-
|
178
|
-
|
228
|
+
[ :dependency,
|
229
|
+
:dependency_condition ].each{|k| context.delete k}
|
230
|
+
|
179
231
|
# build and set context
|
232
|
+
self.attributes = (args[0] || {})
|
180
233
|
if context[:question]
|
181
|
-
context[:dependency] = context[:question].
|
234
|
+
context[:dependency] = context[:question].dependency = self
|
182
235
|
elsif context[:question_group]
|
183
|
-
context[:dependency] = context[:question_group].
|
236
|
+
context[:dependency] = context[:question_group].dependency = self
|
184
237
|
end
|
185
238
|
end
|
186
239
|
end
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
240
|
+
|
241
|
+
# DependencyCondition model
|
242
|
+
module SurveyorParserDependencyConditionMethods
|
243
|
+
DependencyCondition.instance_eval do
|
244
|
+
attr_accessor :question_reference, :answer_reference
|
245
|
+
attr_accessible :question_reference, :answer_reference
|
246
|
+
end
|
247
|
+
def parse_and_build(context, args, original_method, reference_identifier)
|
194
248
|
# clear context
|
195
|
-
context.
|
196
|
-
|
249
|
+
context.delete :dependency_condition
|
250
|
+
|
197
251
|
# build and set context
|
198
252
|
a0, a1, a2 = args
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
}.merge(
|
207
|
-
a2.is_a?(Hash) ? a2 : { :answer_reference =>
|
208
|
-
a2.to_s.gsub(/^a_/, "") }
|
209
|
-
)
|
210
|
-
)
|
211
|
-
end
|
212
|
-
|
213
|
-
def resolve_references
|
214
|
-
if context_reference
|
215
|
-
# Looking up references to questions and answers for linking the dependency objects
|
216
|
-
Surveyor::Parser.rake_trace( (self.question = context_reference[:question_references][question_reference]) ? "found question:#{question_reference} " : "lost! question:#{question_reference} ")
|
217
|
-
context_reference[:answer_references][question_reference] ||= {}
|
218
|
-
Surveyor::Parser.rake_trace( (self.answer = context_reference[:answer_references][question_reference][answer_reference]) ? "found answer:#{answer_reference} " : "lost! answer:#{answer_reference} ")
|
219
|
-
end
|
253
|
+
self.attributes = ({
|
254
|
+
:operator => a1 || "==",
|
255
|
+
:question_reference => a0.to_s.gsub(/^q_/, ""),
|
256
|
+
:rule_key => reference_identifier
|
257
|
+
}.merge( a2.is_a?(Hash) ? a2 : { :answer_reference => a2.to_s.gsub(/^a_/, "") }))
|
258
|
+
context[:dependency].dependency_conditions << context[:dependency_condition] = self
|
259
|
+
context[:dependency_conditions] << self
|
220
260
|
end
|
221
261
|
end
|
222
262
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
def self.parse_and_build(context, args, original_method, reference_identifier)
|
263
|
+
# Answer model
|
264
|
+
module SurveyorParserAnswerMethods
|
265
|
+
def parse_and_build(context, args, original_method, reference_identifier)
|
227
266
|
# clear context
|
228
|
-
|
267
|
+
[ :answer,
|
268
|
+
:validation,
|
269
|
+
:validation_condition ].each{|k| context.delete k}
|
270
|
+
attrs = { :reference_identifier => reference_identifier }.merge(parse_args(args))
|
229
271
|
|
230
|
-
attrs = { :reference_identifier => reference_identifier }.merge(self.parse_args(args))
|
231
|
-
|
232
272
|
# add answers to grid
|
233
273
|
if context[:question_group] && context[:question_group].display_type == "grid"
|
234
|
-
context[:grid_answers] ||= []
|
235
|
-
|
236
|
-
context[:grid_answers] << context[:answer]
|
274
|
+
context[:grid_answers] ||= []
|
275
|
+
self.attributes = ({:display_order => [:grid_answers].size}.merge(attrs))
|
276
|
+
context[:grid_answers] << context[:answer] = self
|
237
277
|
else
|
238
|
-
|
239
|
-
context[:
|
240
|
-
|
278
|
+
self.attributes = ({:display_order => context[:question].answers.size}.merge(attrs))
|
279
|
+
context[:question].answers << context[:answer] = self
|
280
|
+
# keep reference for dependencies
|
281
|
+
unless context[:question].reference_identifier.blank? or reference_identifier.blank?
|
282
|
+
context[:answer_references][context[:question].reference_identifier] ||= {}
|
283
|
+
context[:duplicate_references].push "q_#{context[:question].reference_identifier}, a_#{reference_identifier}" if context[:answer_references][context[:question].reference_identifier].has_key?(reference_identifier)
|
284
|
+
context[:answer_references][context[:question].reference_identifier][reference_identifier] = context[:answer]
|
285
|
+
end
|
241
286
|
end
|
242
287
|
end
|
243
|
-
def
|
288
|
+
def parse_args(args)
|
244
289
|
case args[0]
|
245
290
|
when Hash # Hash
|
246
|
-
|
291
|
+
text_args(args[0][:text]).merge(args[0])
|
247
292
|
when String # (String, Hash) or (String, Symbol, Hash)
|
248
|
-
|
293
|
+
text_args(args[0]).merge(hash_from args[1]).merge(args[2] || {})
|
249
294
|
when Symbol # (Symbol, Hash) or (Symbol, Symbol, Hash)
|
250
|
-
|
295
|
+
symbol_args(args[0]).merge(hash_from args[1]).merge(args[2] || {})
|
251
296
|
else
|
252
|
-
|
297
|
+
text_args(nil)
|
253
298
|
end
|
254
299
|
end
|
255
|
-
def
|
300
|
+
def text_args(text = "Answer")
|
256
301
|
{:text => text.to_s}
|
257
302
|
end
|
258
|
-
def
|
303
|
+
def hash_from(arg)
|
259
304
|
arg.is_a?(Symbol) ? {:response_class => arg.to_s} : arg.is_a?(Hash) ? arg : {}
|
260
305
|
end
|
261
|
-
def
|
306
|
+
def symbol_args(arg)
|
262
307
|
case arg
|
263
308
|
when :other
|
264
|
-
|
309
|
+
text_args("Other")
|
265
310
|
when :other_and_string
|
266
|
-
|
311
|
+
text_args("Other").merge({:response_class => "string"})
|
267
312
|
when :none, :omit # is_exclusive erases and disables other checkboxes and input elements
|
268
|
-
|
313
|
+
text_args(arg.to_s.humanize).merge({:is_exclusive => true})
|
269
314
|
when :integer, :float, :date, :time, :datetime, :text, :datetime, :string
|
270
|
-
|
315
|
+
text_args(arg.to_s.humanize).merge({:response_class => arg.to_s, :display_type => "hidden_label"})
|
271
316
|
end
|
272
317
|
end
|
273
318
|
end
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
def
|
319
|
+
|
320
|
+
# Validation model
|
321
|
+
module SurveyorParserValidationMethods
|
322
|
+
def parse_and_build(context, args, original_method, reference_identifier)
|
278
323
|
# clear context
|
324
|
+
[ :validation,
|
325
|
+
:validation_condition ].each{|k| context.delete k}
|
326
|
+
|
279
327
|
context.delete_if{|k,v| %w(validation validation_condition).map(&:to_sym).include? k}
|
280
328
|
|
281
329
|
# build and set context
|
282
|
-
|
330
|
+
self.attributes = ({:rule => "A"}.merge(args[0] || {}))
|
331
|
+
context[:answer].validations << context[:validation] = self
|
283
332
|
end
|
284
333
|
end
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
def
|
334
|
+
|
335
|
+
# ValidationCondition model
|
336
|
+
module SurveyorParserValidationConditionMethods
|
337
|
+
def parse_and_build(context, args, original_method, reference_identifier)
|
289
338
|
# clear context
|
290
|
-
context.
|
339
|
+
context.delete :validation_condition
|
291
340
|
|
292
341
|
# build and set context
|
293
342
|
a0, a1 = args
|
294
|
-
|
295
|
-
|
296
|
-
|
343
|
+
self.attributes = ({
|
344
|
+
:operator => a0 || "==",
|
345
|
+
:rule_key => reference_identifier}.merge(a1 || {}))
|
346
|
+
context[:validation].validation_conditions << context[:validation_condition] = self
|
297
347
|
end
|
298
348
|
end
|