surveyor_gui 0.0.3

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.
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