surveyor_gui 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (283) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +44 -0
  3. data/.travis.yml +17 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE +21 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +159 -0
  8. data/Rakefile +66 -0
  9. data/app/controllers/answers_controller.rb +3 -0
  10. data/app/controllers/application_controller.rb +3 -0
  11. data/app/controllers/dependencys_controller.rb +286 -0
  12. data/app/controllers/question_groups_controller.rb +84 -0
  13. data/app/controllers/questions_controller.rb +187 -0
  14. data/app/controllers/survey_sections_controller.rb +80 -0
  15. data/app/controllers/surveyforms_controller.rb +4 -0
  16. data/app/controllers/surveyor_controller.rb +89 -0
  17. data/app/controllers/surveyor_gui/reports_controller.rb +339 -0
  18. data/app/controllers/surveyor_gui/responses_controller.rb +39 -0
  19. data/app/controllers/surveyor_gui/survey_controller.rb +16 -0
  20. data/app/facades/report_formatter.rb +44 -0
  21. data/app/facades/report_preview_wrapper.rb +11 -0
  22. data/app/facades/report_response_generator.rb +147 -0
  23. data/app/helpers/application_helper.rb +2 -0
  24. data/app/helpers/dependency_helper.rb +5 -0
  25. data/app/helpers/question_helper.rb +22 -0
  26. data/app/helpers/surveyform_helper.rb +179 -0
  27. data/app/helpers/surveyor_gui/report_helper.rb +19 -0
  28. data/app/helpers/surveyor_helper.rb +4 -0
  29. data/app/inputs/currency_input.rb +5 -0
  30. data/app/inputs/date_picker_input.rb +7 -0
  31. data/app/inputs/datetime_picker_input.rb +5 -0
  32. data/app/inputs/percent_input.rb +5 -0
  33. data/app/inputs/time_picker_input.rb +5 -0
  34. data/app/mailers/.gitkeep +0 -0
  35. data/app/models/.gitkeep +0 -0
  36. data/app/models/answer.rb +4 -0
  37. data/app/models/column.rb +3 -0
  38. data/app/models/dependency.rb +4 -0
  39. data/app/models/dependency_condition.rb +4 -0
  40. data/app/models/permitted_params_decorator.rb +80 -0
  41. data/app/models/question.rb +4 -0
  42. data/app/models/question_group.rb +4 -0
  43. data/app/models/question_type.rb +7 -0
  44. data/app/models/response.rb +4 -0
  45. data/app/models/response_set.rb +4 -0
  46. data/app/models/row.rb +3 -0
  47. data/app/models/survey.rb +4 -0
  48. data/app/models/survey_section.rb +4 -0
  49. data/app/models/surveyform.rb +103 -0
  50. data/app/uploaders/blob_uploader.rb +48 -0
  51. data/app/views/dependencys/_column.html.erb +1 -0
  52. data/app/views/dependencys/_dependency.html.erb +22 -0
  53. data/app/views/dependencys/_dependency_condition_fields.html.erb +48 -0
  54. data/app/views/dependencys/_form.html.erb +20 -0
  55. data/app/views/dependencys/blank.html.erb +0 -0
  56. data/app/views/dependencys/edit.html.erb +1 -0
  57. data/app/views/dependencys/new.html.erb +1 -0
  58. data/app/views/layouts/application.html.erb +14 -0
  59. data/app/views/layouts/surveyor_gui_blank.html.erb +12 -0
  60. data/app/views/layouts/surveyor_gui_default.html.erb +16 -0
  61. data/app/views/layouts/surveyor_modified.html.erb +14 -0
  62. data/app/views/partials/_answer.html.haml +33 -0
  63. data/app/views/partials/_question.html.haml +33 -0
  64. data/app/views/partials/_question_group.html.haml +73 -0
  65. data/app/views/partials/_section.html.haml +13 -0
  66. data/app/views/question_groups/_form.html.erb +56 -0
  67. data/app/views/question_groups/_group_inline_field.html.erb +21 -0
  68. data/app/views/question_groups/_group_inline_fields.html.erb +25 -0
  69. data/app/views/question_groups/blank.html.erb +0 -0
  70. data/app/views/question_groups/edit.html.erb +1 -0
  71. data/app/views/question_groups/new.html.erb +1 -0
  72. data/app/views/questions/_answer_fields.html.erb +23 -0
  73. data/app/views/questions/_answer_options.html.erb +28 -0
  74. data/app/views/questions/_form.html.erb +65 -0
  75. data/app/views/questions/_grid_dropdown_columns.html.erb +10 -0
  76. data/app/views/questions/_grid_dropdown_fields.html.erb +42 -0
  77. data/app/views/questions/_grid_fields.html.erb +9 -0
  78. data/app/views/questions/_no_picks.html.erb +29 -0
  79. data/app/views/questions/_pick.html +21 -0
  80. data/app/views/questions/_picks.html.erb +12 -0
  81. data/app/views/questions/blank.html.erb +0 -0
  82. data/app/views/questions/edit.html.erb +1 -0
  83. data/app/views/questions/new.html.erb +1 -0
  84. data/app/views/survey_sections/_form.html.erb +13 -0
  85. data/app/views/survey_sections/blank.html.erb +0 -0
  86. data/app/views/survey_sections/edit.html.erb +1 -0
  87. data/app/views/survey_sections/new.html.erb +1 -0
  88. data/app/views/surveyforms/_form.html.erb +50 -0
  89. data/app/views/surveyforms/_question_field.html.erb +148 -0
  90. data/app/views/surveyforms/_question_group.html.erb +116 -0
  91. data/app/views/surveyforms/_question_group_fields.html.erb +3 -0
  92. data/app/views/surveyforms/_question_name_and_number.html.erb +6 -0
  93. data/app/views/surveyforms/_question_section.html.erb +15 -0
  94. data/app/views/surveyforms/_question_wrapper.html.erb +109 -0
  95. data/app/views/surveyforms/_survey_section_fields.html.erb +138 -0
  96. data/app/views/surveyforms/clone_survey.html.erb +13 -0
  97. data/app/views/surveyforms/edit.html.erb +5 -0
  98. data/app/views/surveyforms/index.html.erb +40 -0
  99. data/app/views/surveyforms/new.html.erb +1 -0
  100. data/app/views/surveyforms/show.html.erb +5 -0
  101. data/app/views/surveyor_gui/reports/_graphs.html.haml +21 -0
  102. data/app/views/surveyor_gui/reports/_grid.html.haml +42 -0
  103. data/app/views/surveyor_gui/reports/_grid_dropdown.html.haml +56 -0
  104. data/app/views/surveyor_gui/reports/_repeater.html.haml +28 -0
  105. data/app/views/surveyor_gui/reports/_show_report.html.haml +33 -0
  106. data/app/views/surveyor_gui/reports/_single_question.html.haml +70 -0
  107. data/app/views/surveyor_gui/reports/show.html.erb +14 -0
  108. data/app/views/surveyor_gui/responses/_grid.html.haml +20 -0
  109. data/app/views/surveyor_gui/responses/_grid_dropdown.html.haml +20 -0
  110. data/app/views/surveyor_gui/responses/_repeater.html.haml +22 -0
  111. data/app/views/surveyor_gui/responses/_survey_results.html.haml +40 -0
  112. data/app/views/surveyor_gui/responses/index.html.haml +24 -0
  113. data/app/views/surveyor_gui/responses/show.html.haml +42 -0
  114. data/app/views/surveyor_gui/shared/_grid_comments.html.haml +10 -0
  115. data/app/views/surveyor_gui/shared/_new_line.html.haml +2 -0
  116. data/app/views/surveyor_gui/shared/_pick_comments.html.haml +15 -0
  117. data/app/views/surveyor_gui/shared/_question_number.html.haml +9 -0
  118. data/app/views/surveyor_gui/shared/_report_data.html.haml +24 -0
  119. data/app/views/surveyor_gui/shared/_stars_report_data.html.haml +14 -0
  120. data/config.ru +4 -0
  121. data/config/environment.rb +0 -0
  122. data/config/routes.rb +71 -0
  123. data/db/migrate/20140307204049_add_template_to_surveys.rb +5 -0
  124. data/db/migrate/20140307235607_add_test_data_to_response_sets.rb +5 -0
  125. data/db/migrate/20140308171947_add_original_choice_to_answers.rb +5 -0
  126. data/db/migrate/20140308172118_add_blob_to_responses.rb +5 -0
  127. data/db/migrate/20140308172417_add_modifiable_to_survey_section.rb +5 -0
  128. data/db/migrate/20140308174532_add_modifiable_to_question.rb +5 -0
  129. data/db/migrate/20140308175305_add_dynamically_generate_to_questions.rb +5 -0
  130. data/db/migrate/20140311032923_add_dummy_blob_to_questions.rb +5 -0
  131. data/db/migrate/20140311160609_add_dynamic_source_to_questions.rb +5 -0
  132. data/db/migrate/20140311161714_add_report_code_to_questions.rb +5 -0
  133. data/db/migrate/20140530181134_add_is_comment_to_questions.rb +5 -0
  134. data/db/migrate/20140531012006_add_is_comment_to_answers.rb +5 -0
  135. data/db/migrate/20140531225529_create_rows.rb +9 -0
  136. data/db/migrate/20140601011151_create_columns.rb +11 -0
  137. data/db/migrate/20140602030330_add_column_id_to_answers.rb +5 -0
  138. data/db/migrate/20140603155606_add_column_id_to_responses.rb +5 -0
  139. data/db/migrate/20140606023527_add_column_id_to_dependency_conditions.rb +5 -0
  140. data/db/migrate/20140815165307_add_user_id_to_survey.rb +5 -0
  141. data/lib/assets/.gitkeep +0 -0
  142. data/lib/assets/images/addicon.png +0 -0
  143. data/lib/assets/images/datepicker.gif +0 -0
  144. data/lib/assets/images/delete.gif +0 -0
  145. data/lib/assets/images/delete.png +0 -0
  146. data/lib/assets/images/images/border.png +0 -0
  147. data/lib/assets/images/images/controls.png +0 -0
  148. data/lib/assets/images/images/loading.gif +0 -0
  149. data/lib/assets/images/images/loading_background.png +0 -0
  150. data/lib/assets/images/images/overlay.png +0 -0
  151. data/lib/assets/images/rails.png +0 -0
  152. data/lib/assets/images/star.gif +0 -0
  153. data/lib/assets/javascripts/.gitkeep +0 -0
  154. data/lib/assets/javascripts/surveyor_gui/jquery.MetaData.js +121 -0
  155. data/lib/assets/javascripts/surveyor_gui/jquery.blockUI.js +619 -0
  156. data/lib/assets/javascripts/surveyor_gui/jquery.rating.js +377 -0
  157. data/lib/assets/javascripts/surveyor_gui/jquery.validate.js +1188 -0
  158. data/lib/assets/javascripts/surveyor_gui/surveyor_add_ons.js +10 -0
  159. data/lib/assets/javascripts/surveyor_gui/surveyor_gui.js +1417 -0
  160. data/lib/assets/stylesheets/.gitkeep +0 -0
  161. data/lib/assets/stylesheets/surveyor_gui/jquery.rating.css +12 -0
  162. data/lib/assets/stylesheets/surveyor_gui/surveyor_add_ons.css +3 -0
  163. data/lib/assets/stylesheets/surveyor_gui/surveyor_gui.sass +650 -0
  164. data/lib/enumerable_extenders.rb +31 -0
  165. data/lib/generators/surveyor_gui/install_generator.rb +57 -0
  166. data/lib/generators/surveyor_gui/templates/app/assets/javascripts/surveyor_add_ons.js +2 -0
  167. data/lib/generators/surveyor_gui/templates/app/assets/javascripts/surveyor_gui_all.js +24 -0
  168. data/lib/generators/surveyor_gui/templates/app/assets/stylesheets/surveyor_add_ons.css.sass +1 -0
  169. data/lib/generators/surveyor_gui/templates/app/assets/stylesheets/surveyor_gui_all.css.sass +8 -0
  170. data/lib/generators/surveyor_gui/templates/app/helpers/surveyor_helper.rb +4 -0
  171. data/lib/generators/surveyor_gui/templates/app/models/response_set_user.rb +13 -0
  172. data/lib/generators/surveyor_gui/templates/app/views/layouts/surveyor_gui_default.html.erb +16 -0
  173. data/lib/generators/surveyor_gui/templates/config/initializers/simple_form.rb +140 -0
  174. data/lib/generators/surveyor_gui/templates/config/locales/en.yml +5 -0
  175. data/lib/surveyor_gui.rb +17 -0
  176. data/lib/surveyor_gui/engine.rb +30 -0
  177. data/lib/surveyor_gui/helpers/surveyor_helper_methods.rb +19 -0
  178. data/lib/surveyor_gui/models/answer_methods.rb +24 -0
  179. data/lib/surveyor_gui/models/column_methods.rb +43 -0
  180. data/lib/surveyor_gui/models/dependency_condition_methods.rb +53 -0
  181. data/lib/surveyor_gui/models/dependency_methods.rb +83 -0
  182. data/lib/surveyor_gui/models/question_and_group_shared_methods.rb +11 -0
  183. data/lib/surveyor_gui/models/question_group_methods.rb +55 -0
  184. data/lib/surveyor_gui/models/question_methods.rb +435 -0
  185. data/lib/surveyor_gui/models/question_type_methods.rb +493 -0
  186. data/lib/surveyor_gui/models/response_methods.rb +67 -0
  187. data/lib/surveyor_gui/models/response_set_methods.rb +54 -0
  188. data/lib/surveyor_gui/models/row_methods.rb +11 -0
  189. data/lib/surveyor_gui/models/survey_methods.rb +32 -0
  190. data/lib/surveyor_gui/models/survey_section_methods.rb +32 -0
  191. data/lib/surveyor_gui/surveyforms_controller_methods.rb +258 -0
  192. data/lib/surveyor_gui/version.rb +3 -0
  193. data/lib/tasks/.gitkeep +0 -0
  194. data/lib/tasks/surveyor_gui_tasks.rake +4 -0
  195. data/lib/templates/erb/scaffold/_form.html.erb +13 -0
  196. data/spec/controllers/surveyforms_controller_spec.rb +361 -0
  197. data/spec/controllers/surveyor_controller_spec.rb +303 -0
  198. data/spec/factories.rb +181 -0
  199. data/spec/features/create_survey_spec.rb +418 -0
  200. data/spec/features/dependencies_spec.rb +61 -0
  201. data/spec/features/rearrange_survey_spec.rb +118 -0
  202. data/spec/features/ui_spec.rb +469 -0
  203. data/spec/fixtures/REDCapDemoDatabase_DataDictionary.csv +127 -0
  204. data/spec/fixtures/chinese_survey.rb +14 -0
  205. data/spec/fixtures/everything.rb +215 -0
  206. data/spec/fixtures/favorites-ish.rb +22 -0
  207. data/spec/fixtures/favorites.rb +22 -0
  208. data/spec/fixtures/feelings.rb +38 -0
  209. data/spec/fixtures/lifestyle.rb +55 -0
  210. data/spec/fixtures/numbers.rb +21 -0
  211. data/spec/fixtures/redcap_new_headers.csv +1 -0
  212. data/spec/fixtures/redcap_siblings.csv +1 -0
  213. data/spec/fixtures/redcap_whitespace.csv +1 -0
  214. data/spec/helpers/formtastic_custom_input_spec.rb +15 -0
  215. data/spec/helpers/surveyor_helper_spec.rb +116 -0
  216. data/spec/lib/common_spec.rb +37 -0
  217. data/spec/lib/parser_spec.rb +393 -0
  218. data/spec/lib/rake_kitchen_sink.rb +42 -0
  219. data/spec/lib/redcap_parser_spec.rb +129 -0
  220. data/spec/lib/unparser_spec.rb +126 -0
  221. data/spec/models/answer_spec.rb +144 -0
  222. data/spec/models/dependency_condition_spec.rb +428 -0
  223. data/spec/models/dependency_spec.rb +90 -0
  224. data/spec/models/question_group_spec.rb +66 -0
  225. data/spec/models/question_spec.rb +176 -0
  226. data/spec/models/response_set_spec.rb +452 -0
  227. data/spec/models/response_spec.rb +208 -0
  228. data/spec/models/survey_section_spec.rb +58 -0
  229. data/spec/models/survey_spec.rb +155 -0
  230. data/spec/models/surveyor_gui/question_spec.rb +60 -0
  231. data/spec/models/surveyor_gui/question_type_spec.rb +268 -0
  232. data/spec/models/validation_condition_spec.rb +98 -0
  233. data/spec/models/validation_spec.rb +64 -0
  234. data/spec/spec.opts +4 -0
  235. data/spec/spec_helper.rb +119 -0
  236. data/spec/support/scenario_outline_helper.rb +39 -0
  237. data/spec/support/shared.rb +10 -0
  238. data/spec/support/surveyforms_creation_helpers.rb +312 -0
  239. data/spec/support/surveyforms_rearrangement_helpers.rb +170 -0
  240. data/spec/support/surveyor_api_helpers.rb +15 -0
  241. data/spec/support/surveyor_ui_helpers.rb +108 -0
  242. data/spec/support/wait_for_ajax.rb +11 -0
  243. data/spec/views/questions/edit.html.erb_spec.rb +73 -0
  244. data/spec/views/surveyforms/edit.html.erb_spec.rb +126 -0
  245. data/surveyor_gui.gemspec +52 -0
  246. data/test/dummy/README.rdoc +261 -0
  247. data/test/dummy/Rakefile +7 -0
  248. data/test/dummy/app/assets/javascripts/application.js +15 -0
  249. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  250. data/test/dummy/app/controllers/application_controller.rb +3 -0
  251. data/test/dummy/app/helpers/application_helper.rb +2 -0
  252. data/test/dummy/app/mailers/.gitkeep +0 -0
  253. data/test/dummy/app/models/.gitkeep +0 -0
  254. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  255. data/test/dummy/config.ru +4 -0
  256. data/test/dummy/config/application.rb +59 -0
  257. data/test/dummy/config/boot.rb +10 -0
  258. data/test/dummy/config/database.yml +25 -0
  259. data/test/dummy/config/environment.rb +5 -0
  260. data/test/dummy/config/environments/development.rb +37 -0
  261. data/test/dummy/config/environments/production.rb +67 -0
  262. data/test/dummy/config/environments/test.rb +37 -0
  263. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  264. data/test/dummy/config/initializers/inflections.rb +15 -0
  265. data/test/dummy/config/initializers/mime_types.rb +5 -0
  266. data/test/dummy/config/initializers/secret_token.rb +7 -0
  267. data/test/dummy/config/initializers/session_store.rb +8 -0
  268. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  269. data/test/dummy/config/locales/en.yml +5 -0
  270. data/test/dummy/config/routes.rb +58 -0
  271. data/test/dummy/lib/assets/.gitkeep +0 -0
  272. data/test/dummy/log/.gitkeep +0 -0
  273. data/test/dummy/public/404.html +26 -0
  274. data/test/dummy/public/422.html +26 -0
  275. data/test/dummy/public/500.html +25 -0
  276. data/test/dummy/public/favicon.ico +0 -0
  277. data/test/dummy/script/rails +6 -0
  278. data/test/surveyor-gui_test.rb +7 -0
  279. data/test/test_helper.rb +15 -0
  280. data/vendor/assets/stylesheets/.gitkeep +0 -0
  281. data/vendor/assets/stylesheets/custom.sass +5 -0
  282. data/vendor/plugins/.gitkeep +0 -0
  283. metadata +664 -0
@@ -0,0 +1,493 @@
1
+ module SurveyorGui
2
+ module Models
3
+ module QuestionTypeMethods
4
+
5
+ attr_accessor :id, :text, :part_of_group, :pick, :display_type, :group_display_type, :response_class
6
+
7
+ def initialize(args)
8
+ @id = args[:id]
9
+ @text = args[:text]
10
+ @part_of_group = args[:part_of_group]
11
+ @pick = args[:pick]
12
+ @display_type = args[:display_type]
13
+ @group_display_type = args[:group_display_type]
14
+ @response_class = args[:response_class]
15
+ end
16
+
17
+ def self.included(base)
18
+ base.send :extend, ClassMethods
19
+ end
20
+
21
+ def persisted?
22
+ false
23
+ end
24
+
25
+ def grid?
26
+ @id == :grid_one || @id == :grid_any
27
+ end
28
+
29
+ def build_complex_question_structure(question, args)
30
+ #looks at id and calls the appropriate methods, eg.
31
+ #if question_type.id is pick_one, calls _build_pick_one
32
+ question.reload
33
+ #puts question.attributes
34
+ builder = "_build_"+id.to_s
35
+ send builder.to_sym, question, args
36
+ end
37
+
38
+ private
39
+
40
+ def _build_pick_one(question, args)
41
+ _process_answers_textbox(question, args)
42
+ end
43
+
44
+ def _build_pick_any(question, args)
45
+ _process_answers_textbox(question, args)
46
+ end
47
+
48
+ def _build_slider(question, args)
49
+ _process_answers_textbox(question, args)
50
+ end
51
+
52
+ def _build_stars(question, args)
53
+ end
54
+
55
+ def _build_dropdown(question, args)
56
+ _process_answers_textbox(question, args)
57
+ end
58
+
59
+ def _build_grid_one(question, args)
60
+ _build_grid(question,args)
61
+ end
62
+
63
+ def _build_grid_any(question, args)
64
+ _build_grid(question,args)
65
+ end
66
+
67
+ def _build_grid_dropdown(question, args)
68
+ _build_grid_dropdown(question,args)
69
+ end
70
+
71
+ def _build_grid(question,args)
72
+ is_exclusive = args[:is_exclusive]
73
+ omit_text = args[:omit_text].to_s
74
+ grid_columns_textbox = args[:grid_columns_textbox]
75
+ grid_rows_textbox = args[:grid_rows_textbox]
76
+ other = args[:other]
77
+ other_text = args[:other_text].to_s
78
+ is_comment = args[:comments]
79
+ comments_text = args[:comments_text].to_s
80
+ _cleanup_orphan_grid_dropdown_answers(question)
81
+ _process_grid_rows_textbox(question, grid_rows_textbox)
82
+ _process_grid_answers(
83
+ question,
84
+ grid_columns_textbox,
85
+ is_exclusive, omit_text,
86
+ other, other_text,
87
+ is_comment, comments_text
88
+ )
89
+ _restore_question_group(question)
90
+ end
91
+
92
+ def _build_grid_dropdown(question,args)
93
+ is_exclusive = args[:is_exclusive]
94
+ omit_text = args[:omit_text].to_s
95
+ grid_columns_textbox = args[:grid_columns_textbox]
96
+ grid_rows_textbox = args[:grid_rows_textbox]
97
+ other = args[:other]
98
+ other_text = args[:other_text].to_s
99
+ is_comment = args[:comments]
100
+ comments_text = args[:comments_text].to_s
101
+ _process_grid_rows_textbox(question, grid_rows_textbox)
102
+ _process_grid_columns_textbox(
103
+ question,
104
+ is_exclusive, omit_text,
105
+ other, other_text,
106
+ is_comment, comments_text
107
+ )
108
+ _create_a_comment(question, is_comment, comments_text)
109
+ _restore_question_group(question)
110
+ end
111
+
112
+ def _process_answers_textbox(question, args)
113
+ is_exclusive = args[:is_exclusive]
114
+ other = args[:other]
115
+ is_comment = args[:comments]
116
+ omit_text = is_exclusive ? "\n"+args[:omit_text].to_s : ""
117
+ other_text = other ? "\n"+args[:other_text].to_s : ""
118
+ comments_text = is_comment ? "\n"+args[:comments_text].to_s : ""
119
+ answers_textbox = args[:answers_textbox]
120
+ updated_answers = TextBoxParser.new(
121
+ textbox: answers_textbox,
122
+ records_to_update: question.answers
123
+ )
124
+ updated_answers.update_or_create_records do |display_order, text|
125
+ _create_an_answer(display_order, text, question)
126
+ end
127
+ _create_an_other_answer(question, other, other_text)
128
+ _create_an_omit_answer(question, is_exclusive, omit_text)
129
+ _create_a_comment_answer(question, is_comment, comments_text)
130
+ end
131
+
132
+ def _process_grid_rows_textbox(
133
+ question,
134
+ grid_rows_textbox
135
+ )
136
+ #puts "processing grid rows \ntextbox grid?: #{_grid?(question)} \ntb: #{grid_rows_textbox} \ntb: #{grid_columns_textbox}\nthis: #{question.id}\ntext: #{question.text}"
137
+ #puts 'got to inner if'
138
+ #puts "\n\n#{question.display_order}\n\n"
139
+ display_order_of_first_question_in_group = question.display_order
140
+ grid_rows = TextBoxParser.new(
141
+ textbox: grid_rows_textbox,
142
+ records_to_update: question.question_group.questions,
143
+ starting_display_order: display_order_of_first_question_in_group
144
+ )
145
+ grid_rows.update_or_create_records(pick: question.pick, display_type: question.display_type) \
146
+ do |display_order, new_text|
147
+ current_question = _create_a_question(question, display_order, new_text)
148
+ #puts "current question: #{current_question.text} #{current_question.question_group_id} saved? #{current_question.persisted?} id: #{current_question.id}"
149
+ end
150
+ end
151
+
152
+ def _process_grid_answers(
153
+ question,
154
+ grid_columns_textbox,
155
+ is_exclusive, omit_text,
156
+ other, other_text,
157
+ is_comment, comments_text,
158
+ column_id=nil
159
+ )
160
+ question.question_group.questions.is_not_comment.each do |question|
161
+ _create_some_answers(question, grid_columns_textbox, column_id)
162
+ _create_an_other_answer(question, other, other_text, column_id)
163
+ _create_an_omit_answer(question, is_exclusive, omit_text)
164
+ end
165
+ _create_a_comment(question, is_comment, comments_text) if id != :grid_dropdown
166
+ end
167
+
168
+ def _cleanup_orphan_grid_dropdown_answers(question)
169
+ if question.question_group
170
+ question.question_group.questions.map{|q| q.answers.where('column_id IS NOT NULL').map{|a| a.destroy}}
171
+ question.question_group.columns.map{|c| c.destroy}
172
+ end
173
+ end
174
+
175
+ def _restore_question_group(question)
176
+ #work around for infernal :dependent=>:destroy on belongs_to :question_group from Surveyor
177
+ #can't seem to override it and everytime a question is deleted, the whole group goes with it.
178
+ #which makes it impossible to delete a question from a grid.
179
+ begin
180
+ QuestionGroup.find(question.question_group)
181
+ rescue
182
+ QuestionGroup.create!(question.question_group.attributes)
183
+ end
184
+ end
185
+
186
+ def _process_grid_columns_textbox(
187
+ question,
188
+ is_exclusive, omit_text,
189
+ other, other_text,
190
+ is_comment, comments_text
191
+ )
192
+ question.question_group.columns.each do |column|
193
+ _process_grid_answers(
194
+ question,
195
+ column.answers_textbox,
196
+ is_exclusive, omit_text,
197
+ other, other_text,
198
+ is_comment, comments_text,
199
+ column.id
200
+ )
201
+ end
202
+ end
203
+
204
+ def _pick?
205
+ !(pick=="none")
206
+ end
207
+
208
+ def _grid?(question)
209
+ [:grid_one, :grid_any, :grid_dropdown].include? self.id
210
+ end
211
+
212
+ def _create_some_answers(current_question, grid_columns_textbox, column_id)
213
+ if grid_columns_textbox.nil?
214
+ grid_columns_textbox = " "
215
+ end
216
+ columns = TextBoxParser.new(
217
+ textbox: grid_columns_textbox,
218
+ records_to_update: current_question.answers.where('column_id=? or column_id IS NULL',column_id)
219
+ )
220
+ columns.update_or_create_records do |display_order, text|
221
+ _create_an_answer(display_order, text, current_question, column_id: column_id)
222
+ end
223
+
224
+ end
225
+
226
+
227
+ def _create_an_answer(display_order, new_text, current_question, args={})
228
+ params = {
229
+ question_id: current_question.id,
230
+ display_order: display_order,
231
+ text: new_text
232
+ }.merge(args)
233
+
234
+ Answer.create!(params)
235
+ end
236
+
237
+ def _create_an_other_answer(question, other, other_text, column_id=nil)
238
+ if other
239
+ display_order = question.answers.last.display_order+1
240
+ _create_an_answer(display_order, other_text, question, response_class: "string", column_id: column_id)
241
+ end
242
+ end
243
+
244
+ def _create_an_omit_answer(question, is_exclusive, omit_text)
245
+ if is_exclusive
246
+ display_order = question.answers.size > 0 ? question.answers.last.display_order+1 : 0
247
+ _create_an_answer(display_order, omit_text, question, is_exclusive: is_exclusive)
248
+ end
249
+ end
250
+
251
+ def _create_a_comment_answer(question, is_comment, comments_text)
252
+ if is_comment
253
+ display_order = question.answers.order('display_order ASC').last.display_order
254
+ answer = _create_an_answer(display_order, comments_text, question, response_class: "string", is_comment: true)
255
+ end
256
+ end
257
+
258
+ def _create_a_comment(question, is_comment, comments_text)
259
+ if is_comment
260
+ display_order = question.next_display_order
261
+ question = _create_a_question(question, display_order,comments_text, is_comment: true, pick: "none", display_type: "default")
262
+ answer = _create_an_answer(0, comments_text, question, response_class: "string")
263
+ answer.update_attribute(:text, "")
264
+ end
265
+ end
266
+
267
+ def _create_a_question(question, display_order, new_text, args={})
268
+ #puts "making question #{new_text}"
269
+ #puts "\n\n#{self.display_order}\n\n"
270
+ params = {
271
+ display_order: display_order,
272
+ text: new_text,
273
+ survey_section_id: question.survey_section_id,
274
+ question_group_id: question.question_group_id,
275
+ pick: question.pick,
276
+ reference_identifier: question.reference_identifier,
277
+ display_type: question.display_type,
278
+ is_mandatory: question.is_mandatory,
279
+ prefix: question.prefix,
280
+ suffix: question.suffix,
281
+ decimals: question.decimals,
282
+ modifiable: question.modifiable,
283
+ report_code: question.report_code
284
+ }.merge(args)
285
+ return Question.create!(params)
286
+ end
287
+
288
+
289
+ #----------------------------- end instance methods ---------------------------------------------------------------
290
+ module ClassMethods
291
+
292
+ AllTypes = [
293
+ # group answer
294
+ # part_of_ display display response
295
+ #id #text group? pick type type class
296
+ [:pick_one, "Multiple Choice (only one answer)" , false, :one, "default", nil, :all],
297
+ [:pick_any, "Multiple Choice (multiple answers)" , false, :any, "default", nil, :all],
298
+ [:box, "Text Box (for extended text, like notes, etc.)" , false, :none, "default", nil, :text],
299
+ [:dropdown, "Dropdown List" , false, :one, :dropdown, nil, :all],
300
+ [:string, "Text" , false, :none, "default", nil, :string],
301
+ [:number, "Number" , false, :none, "default", nil, :float],
302
+ [:number, "Number" , false, :none, "default", nil, :integer],
303
+ [:date, "Date" , false, :none, "default", nil, :date],
304
+ [:datetime, "Date and Time" , false, :none, "default", nil, :datetime],
305
+ [:time, "Time" , false, :none, "default", nil, :time],
306
+ [:slider, "Slider" , false, :one, :slider, nil, :all],
307
+ [:stars, "1-5 Stars" , false, :one, :stars, nil, :all],
308
+ [:label, "Label" , false, :none, :label, nil, :all],
309
+ [:file, "File Upload" , false, :none, "default", nil, :blob],
310
+ [:grid_one, "Grid (pick one)" , true, :one, "default", :grid, :all],
311
+ [:grid_any, "Grid (pick any)" , true, :any, "default", :grid, :all],
312
+ [:grid_dropdown, "Grid (dropdowns)" , true, :one, :dropdown, :grid, :all],
313
+ [:group_inline, "Inline Question Group" , true, nil, nil, :inline, :all],
314
+ [:group_default, "Question Group" , true, nil, nil, :default, :all],
315
+ [:repeater, "Repeater (multiple responses)" , true, nil, :all, :repeater, :all],
316
+ #nothing below here shows up on the question builder choices for question type
317
+ [:pick_one, "Multiple Choice (only one answer)" , true, :one, "default", :inline, :all],
318
+ [:pick_any, "Multiple Choice (multiple answers)" , true, :any, "default", :inline, :all],
319
+ [:box, "Text Box (for extended text, like notes, etc.)" , true, :none, "default", :inline, :text],
320
+ [:dropdown, "Dropdown List" , true, :one, :dropdown, :inline, :all],
321
+ [:string, "Text" , true, :none, "default", :inline, :string],
322
+ [:number, "Number" , true, :none, "default", :inline, :float],
323
+ [:number, "Number" , true, :none, "default", :inline, :integer],
324
+ [:date, "Date" , true, :none, "default", :inline, :date],
325
+ [:datetime, "Date and Time" , true, :none, "default", :inline, :datetime],
326
+ [:time, "Time" , true, :none, "default", :inline, :time],
327
+ [:slider, "Slider" , true, :one, :slider, :inline, :all],
328
+ [:stars, "1-5 Stars" , true, :one, :stars, :inline, :all],
329
+ [:label, "Label" , true, :none, :label, :inline, :all],
330
+ [:file, "File Upload" , true, :none, "default", :inline, :blob],
331
+ [:string, "Text" , true, :none, :default, :grid, :all],
332
+
333
+
334
+ [:pick_one, "Multiple Choice (only one answer)" , true, :one, "default",:default, :all],
335
+ [:pick_any, "Multiple Choice (multiple answers)" , true, :any, "default",:default, :all],
336
+ [:box, "Text Box (for extended text, like notes, etc.)" , true, :none, "default", :default, :text],
337
+ [:dropdown, "Dropdown List" , true, :one, :dropdown, :default, :all],
338
+ [:string, "Text" , true, :none, "default", :default, :string],
339
+ [:number, "Number" , true, :none, "default", :default, :float],
340
+ [:number, "Number" , true, :none, "default", :default, :integer],
341
+ [:date, "Date" , true, :none, "default", :default, :date],
342
+ [:datetime, "Date and Time" , true, :none, "default", :default, :datetime],
343
+ [:time, "Time" , true, :none, "default", :default, :time],
344
+ [:slider, "Slider" , true, :one, :slider, :default, :all],
345
+ [:stars, "1-5 Stars" , true, :one, :stars, :default, :all],
346
+ [:label, "Label" , true, :none, :label, :default, :all],
347
+ [:file, "File Upload" , true, :none, "default", :default, :blob],
348
+
349
+ [:pick_one, "Multiple Choice (only one answer)" , true, :one, "default",:repeater, :all],
350
+ [:pick_any, "Multiple Choice (multiple answers)" , true, :any, "default",:repeater, :all],
351
+ [:box, "Text Box (for extended text, like notes, etc.)" , true, :none, "default", :repeater, :text],
352
+ [:dropdown, "Dropdown List" , true, :one, :dropdown, :repeater, :all],
353
+ [:string, "Text" , true, :none, "default", :repeater, :string],
354
+ [:number, "Number" , true, :none, "default", :repeater, :float],
355
+ [:number, "Number" , true, :none, "default", :repeater, :integer],
356
+ [:date, "Date" , true, :none, "default", :repeater, :date],
357
+ [:datetime, "Date and Time" , true, :none, "default", :repeater, :datetime],
358
+ [:time, "Time" , true, :none, "default", :repeater, :time],
359
+ [:slider, "Slider" , true, :one, :slider, :repeater, :all],
360
+ [:stars, "1-5 Stars" , true, :one, :stars, :repeater, :all],
361
+ [:label, "Label" , true, :none, :label, :repeater, :all],
362
+ [:file, "File Upload" , true, :none, "default", :repeater, :blob],
363
+
364
+ [:string, "Text" , true, :none, :default, :grid, :all],
365
+ #surveyor seems to have an inline option that doesn't actually render inline yet. Recognize it
366
+ #but don't treat it differently. See question 16 and 17 in kitchen_sink_survey.rb.
367
+ [:pick_one, "Multiple Choice (only one answer)" , true, :one, "inline", nil, :answer],
368
+ [:pick_any, "Multiple Choice (multiple answers)" , true, :any, "inline", nil, :answer],
369
+ [:pick_one, "Multiple Choice (only one answer)" , false, :one, "inline", nil, :answer],
370
+ [:pick_any, "Multiple Choice (multiple answers)" , false, :any, "inline", nil, :answer]
371
+ ]
372
+
373
+
374
+ def categorize_question(question)
375
+ question_group_display_type = question.part_of_group? ? question.question_group.display_type : ""
376
+ answer = question.answers.first
377
+ all.each do |question_type|
378
+ return question_type.id if _match_found(question, question_type, question_group_display_type, answer)
379
+ end
380
+ raise "No question_type matches question #{question.id}"
381
+ end
382
+
383
+ def all
384
+ arr = []
385
+ type = Struct.new(:id, :text, :part_of_group, :pick, :display_type, :group_display_type, :response_class)
386
+ AllTypes.each do |t|
387
+ arr << QuestionType.new(id: t[0],
388
+ text: t[1],
389
+ part_of_group: t[2],
390
+ pick: t[3],
391
+ display_type: t[4],
392
+ group_display_type: t[5],
393
+ response_class: t[6]
394
+ )
395
+ end
396
+ arr
397
+ end
398
+
399
+ def find(id)
400
+ all.select{|qt| qt.id == id}[0]
401
+ end
402
+
403
+ private
404
+
405
+ def _match_found(question, question_type, question_group_display_type, answer)
406
+ answer_response_class = answer ? answer.response_class : "string"
407
+
408
+ _match(question.part_of_group?, question_type.part_of_group, :part_of_group) &&
409
+ _match(question.pick, question_type.pick.to_s, :pick) &&
410
+ _match(question.display_type.to_s, question_type.display_type.to_s, :display_type) &&
411
+ _match(question_group_display_type, question_type.group_display_type.to_s, :group_display_type) &&
412
+ _match(answer_response_class, question_type.response_class.to_s, :response_class)
413
+ end
414
+
415
+ def _match(question_attribute, question_type_attribute, match_attribute)
416
+ (question_attribute == question_type_attribute) ||
417
+ (question_type_attribute == "all")
418
+ end
419
+ end
420
+ end
421
+
422
+ end
423
+ end
424
+
425
+ class TextBoxParser
426
+ include Enumerable
427
+ def initialize(args)
428
+ @text = args[:textbox].to_s.gsub("\r","")
429
+ @nested_objects = args[:records_to_update]
430
+ @starting_display_order = args.fetch(:starting_display_order,0)
431
+ end
432
+
433
+ def each(&block)
434
+ _lines.readlines.each(&block)
435
+ end
436
+
437
+ def update_or_create_records(update_params={}, &create_object)
438
+ #takes a code block to customize creation of new objects
439
+ #update and delete operations are always the same. For now.
440
+ _lines.readlines.each_with_index do |line, display_order|
441
+ _update_or_create(
442
+ line.strip,
443
+ display_order + @starting_display_order,
444
+ update_params,
445
+ &create_object
446
+ ) unless line.blank?
447
+ end
448
+ _delete_orphans
449
+ end
450
+
451
+ private
452
+
453
+ def _lines
454
+ StringIO.new(@text)
455
+ end
456
+
457
+ def _update_or_create(text, display_order, update_params={}, &create_object)
458
+ nested_objects = _find_nested_if_exists(text)
459
+ if nested_objects.empty?
460
+ create_object.call(display_order, text)
461
+ else
462
+ _update_nested_object(nested_objects.first, display_order, update_params)
463
+ end
464
+ end
465
+
466
+ def _delete_orphans
467
+ valid_rows = @text.split("\n")
468
+ valid_rows = valid_rows.map{|vr| vr.strip}
469
+ @nested_objects.reload
470
+ @nested_objects.each do |nested_object|
471
+ #puts "possibly deleting #{nested_object.class.name} #{nested_object.id} #{nested_object.text.rstrip} valid #{valid_rows}"
472
+ nested_object.destroy unless valid_rows.include? "#{nested_object.text.rstrip}"
473
+ end
474
+ _dedupe
475
+ end
476
+
477
+ def _find_nested_if_exists(text)
478
+ @nested_objects.where('text = ?',text)
479
+ end
480
+
481
+ def _update_nested_object(nested_object, index, update_params)
482
+ params = {:display_order=>index}.merge(update_params)
483
+ nested_object.update_attributes(params)
484
+ end
485
+
486
+ def _dedupe
487
+ grouped = @nested_objects.order('display_order DESC').uniq{|n| n.id}.collect(&:id)
488
+ @nested_objects.each do |obj|
489
+ obj.destroy unless (grouped.include? obj.id)
490
+ end
491
+ end
492
+
493
+ end