hssc_surveyor 1.4.1.pre

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 (212) hide show
  1. data/.gitignore +28 -0
  2. data/.rspec +1 -0
  3. data/CHANGELOG.md +198 -0
  4. data/Gemfile +5 -0
  5. data/Gemfile.rails_version +19 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +186 -0
  8. data/Rakefile +105 -0
  9. data/app/controllers/surveyor_controller.rb +6 -0
  10. data/app/helpers/results_helper.rb +20 -0
  11. data/app/helpers/survey_form_builder.rb +37 -0
  12. data/app/helpers/surveyor_helper.rb +3 -0
  13. data/app/inputs/quiet_input.rb +5 -0
  14. data/app/inputs/surveyor_check_boxes_input.rb +35 -0
  15. data/app/inputs/surveyor_radio_input.rb +18 -0
  16. data/app/models/answer.rb +4 -0
  17. data/app/models/dependency.rb +4 -0
  18. data/app/models/dependency_condition.rb +4 -0
  19. data/app/models/question.rb +4 -0
  20. data/app/models/question_group.rb +5 -0
  21. data/app/models/response.rb +5 -0
  22. data/app/models/response_set.rb +4 -0
  23. data/app/models/survey.rb +4 -0
  24. data/app/models/survey_section.rb +5 -0
  25. data/app/models/survey_section_sweeper.rb +15 -0
  26. data/app/models/survey_translation.rb +5 -0
  27. data/app/models/validation.rb +4 -0
  28. data/app/models/validation_condition.rb +4 -0
  29. data/app/views/layouts/results.html.erb +13 -0
  30. data/app/views/layouts/surveyor_default.html.erb +12 -0
  31. data/app/views/partials/_answer.html.haml +25 -0
  32. data/app/views/partials/_dependents.html.haml +5 -0
  33. data/app/views/partials/_question.html.haml +41 -0
  34. data/app/views/partials/_question_group.html.haml +44 -0
  35. data/app/views/partials/_section.html.haml +12 -0
  36. data/app/views/partials/_section_menu.html.haml +12 -0
  37. data/app/views/surveyor/edit.html.haml +24 -0
  38. data/app/views/surveyor/export.json.rabl +85 -0
  39. data/app/views/surveyor/new.html.haml +24 -0
  40. data/app/views/surveyor/show.html.haml +74 -0
  41. data/app/views/surveyor/show.json.rabl +15 -0
  42. data/ci-exec.sh +56 -0
  43. data/config/routes.rb +8 -0
  44. data/cucumber.yml +10 -0
  45. data/doc/REPRESENTATIONS.md +34 -0
  46. data/doc/api_id_schema.json +7 -0
  47. data/doc/question types.png +0 -0
  48. data/doc/response_set_schema.json +54 -0
  49. data/doc/surveyor question combinations.png +0 -0
  50. data/doc/surveyor reject or delete decision matrix.png +0 -0
  51. data/doc/surveyor_models.png +0 -0
  52. data/doc/surveyor_models2.png +0 -0
  53. data/doc/surveyor_timestamp_schema.json +9 -0
  54. data/features/ajax_submissions.feature +140 -0
  55. data/features/export_to_json.feature +344 -0
  56. data/features/internationalization.feature +121 -0
  57. data/features/no_duplicates.feature +110 -0
  58. data/features/show_survey.feature +71 -0
  59. data/features/step_definitions/parser_steps.rb +145 -0
  60. data/features/step_definitions/surveyor_steps.rb +325 -0
  61. data/features/step_definitions/ui_steps.rb +25 -0
  62. data/features/step_definitions/web_steps.rb +225 -0
  63. data/features/support/REDCapDemoDatabase_DataDictionary.csv +127 -0
  64. data/features/support/database_cleaner.rb +16 -0
  65. data/features/support/env.rb +56 -0
  66. data/features/support/hooks.rb +4 -0
  67. data/features/support/paths.rb +39 -0
  68. data/features/support/redcap_new_headers.csv +1 -0
  69. data/features/support/redcap_siblings.csv +1 -0
  70. data/features/support/redcap_whitespace.csv +1 -0
  71. data/features/support/selectors.rb +39 -0
  72. data/features/support/simultaneous_ajax.rb +101 -0
  73. data/features/support/single_quit_selenium_driver.rb +23 -0
  74. data/features/support/slow_updates.rb +18 -0
  75. data/features/surveyor.feature +895 -0
  76. data/features/surveyor_dependencies.feature +476 -0
  77. data/features/surveyor_parser.feature +504 -0
  78. data/features/z_redcap_parser.feature +62 -0
  79. data/lib/assets/images/surveyor/next.gif +0 -0
  80. data/lib/assets/images/surveyor/prev.gif +0 -0
  81. data/lib/assets/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  82. data/lib/assets/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  83. data/lib/assets/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  84. data/lib/assets/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  85. data/lib/assets/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  86. data/lib/assets/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  87. data/lib/assets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  88. data/lib/assets/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  89. data/lib/assets/images/ui-icons_222222_256x240.png +0 -0
  90. data/lib/assets/images/ui-icons_2e83ff_256x240.png +0 -0
  91. data/lib/assets/images/ui-icons_454545_256x240.png +0 -0
  92. data/lib/assets/images/ui-icons_888888_256x240.png +0 -0
  93. data/lib/assets/images/ui-icons_cd0a0a_256x240.png +0 -0
  94. data/lib/assets/javascripts/surveyor/jquery-1.9.0.js +9555 -0
  95. data/lib/assets/javascripts/surveyor/jquery-ui-1.10.0.custom.js +14850 -0
  96. data/lib/assets/javascripts/surveyor/jquery-ui-timepicker-addon.js +1919 -0
  97. data/lib/assets/javascripts/surveyor/jquery.maskedinput.js +338 -0
  98. data/lib/assets/javascripts/surveyor/jquery.selectToUISlider.js +240 -0
  99. data/lib/assets/javascripts/surveyor/jquery.surveyor.js +156 -0
  100. data/lib/assets/stylesheets/surveyor/jquery-ui-1.10.0.custom.css +1174 -0
  101. data/lib/assets/stylesheets/surveyor/jquery-ui-timepicker-addon.css +11 -0
  102. data/lib/assets/stylesheets/surveyor/reset.css +48 -0
  103. data/lib/assets/stylesheets/surveyor/results.css +125 -0
  104. data/lib/assets/stylesheets/surveyor/ui.slider.extras.css +110 -0
  105. data/lib/assets/stylesheets/surveyor.sass +132 -0
  106. data/lib/generators/surveyor/custom_generator.rb +18 -0
  107. data/lib/generators/surveyor/install_generator.rb +102 -0
  108. data/lib/generators/surveyor/templates/app/assets/javascripts/surveyor_all.js +6 -0
  109. data/lib/generators/surveyor/templates/app/assets/stylesheets/surveyor_all.css +9 -0
  110. data/lib/generators/surveyor/templates/app/controllers/surveyor_controller.rb +40 -0
  111. data/lib/generators/surveyor/templates/app/views/layouts/surveyor_custom.html.erb +13 -0
  112. data/lib/generators/surveyor/templates/config/locales/surveyor_en.yml +19 -0
  113. data/lib/generators/surveyor/templates/config/locales/surveyor_es.yml +19 -0
  114. data/lib/generators/surveyor/templates/config/locales/surveyor_he.yml +19 -0
  115. data/lib/generators/surveyor/templates/config/locales/surveyor_ko.yml +19 -0
  116. data/lib/generators/surveyor/templates/db/migrate/add_api_id_to_question_groups.rb +10 -0
  117. data/lib/generators/surveyor/templates/db/migrate/add_api_ids.rb +14 -0
  118. data/lib/generators/surveyor/templates/db/migrate/add_api_ids_to_response_sets_and_responses.rb +12 -0
  119. data/lib/generators/surveyor/templates/db/migrate/add_attachment_to_response.rb +5 -0
  120. data/lib/generators/surveyor/templates/db/migrate/add_correct_answer_id_to_questions.rb +10 -0
  121. data/lib/generators/surveyor/templates/db/migrate/add_default_value_to_answers.rb +10 -0
  122. data/lib/generators/surveyor/templates/db/migrate/add_display_order_to_surveys.rb +10 -0
  123. data/lib/generators/surveyor/templates/db/migrate/add_display_type_to_answers.rb +14 -0
  124. data/lib/generators/surveyor/templates/db/migrate/add_index_to_response_sets.rb +10 -0
  125. data/lib/generators/surveyor/templates/db/migrate/add_index_to_surveys.rb +10 -0
  126. data/lib/generators/surveyor/templates/db/migrate/add_input_mask_attributes_to_answer.rb +12 -0
  127. data/lib/generators/surveyor/templates/db/migrate/add_section_id_to_responses.rb +12 -0
  128. data/lib/generators/surveyor/templates/db/migrate/add_unique_index_on_access_code_and_version_in_surveys.rb +10 -0
  129. data/lib/generators/surveyor/templates/db/migrate/add_unique_indicies.rb +18 -0
  130. data/lib/generators/surveyor/templates/db/migrate/add_version_to_surveys.rb +10 -0
  131. data/lib/generators/surveyor/templates/db/migrate/api_ids_must_be_unique.rb +23 -0
  132. data/lib/generators/surveyor/templates/db/migrate/create_answers.rb +38 -0
  133. data/lib/generators/surveyor/templates/db/migrate/create_dependencies.rb +23 -0
  134. data/lib/generators/surveyor/templates/db/migrate/create_dependency_conditions.rb +30 -0
  135. data/lib/generators/surveyor/templates/db/migrate/create_question_groups.rb +28 -0
  136. data/lib/generators/surveyor/templates/db/migrate/create_questions.rb +37 -0
  137. data/lib/generators/surveyor/templates/db/migrate/create_response_sets.rb +23 -0
  138. data/lib/generators/surveyor/templates/db/migrate/create_responses.rb +34 -0
  139. data/lib/generators/surveyor/templates/db/migrate/create_survey_sections.rb +30 -0
  140. data/lib/generators/surveyor/templates/db/migrate/create_survey_translations.rb +19 -0
  141. data/lib/generators/surveyor/templates/db/migrate/create_surveys.rb +32 -0
  142. data/lib/generators/surveyor/templates/db/migrate/create_validation_conditions.rb +33 -0
  143. data/lib/generators/surveyor/templates/db/migrate/create_validations.rb +21 -0
  144. data/lib/generators/surveyor/templates/db/migrate/drop_unique_index_on_access_code_in_surveys.rb +10 -0
  145. data/lib/generators/surveyor/templates/db/migrate/update_blank_api_ids_on_question_group.rb +22 -0
  146. data/lib/generators/surveyor/templates/db/migrate/update_blank_versions_on_surveys.rb +13 -0
  147. data/lib/generators/surveyor/templates/surveys/EXTENDING_SURVEYOR.md +52 -0
  148. data/lib/generators/surveyor/templates/surveys/MODIFYING_SURVEYOR.md +91 -0
  149. data/lib/generators/surveyor/templates/surveys/date_survey.rb +16 -0
  150. data/lib/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +284 -0
  151. data/lib/generators/surveyor/templates/surveys/languages.rb +14 -0
  152. data/lib/generators/surveyor/templates/surveys/quiz.rb +11 -0
  153. data/lib/generators/surveyor/templates/surveys/translations/languages.es.yml +18 -0
  154. data/lib/generators/surveyor/templates/surveys/translations/languages.he.yml +18 -0
  155. data/lib/generators/surveyor/templates/surveys/translations/languages.ko.yml +18 -0
  156. data/lib/generators/surveyor/templates/vendor/assets/stylesheets/custom.sass +5 -0
  157. data/lib/surveyor/acts_as_response.rb +17 -0
  158. data/lib/surveyor/common.rb +59 -0
  159. data/lib/surveyor/engine.rb +10 -0
  160. data/lib/surveyor/helpers/asset_pipeline.rb +13 -0
  161. data/lib/surveyor/helpers/formtastic_custom_input.rb +13 -0
  162. data/lib/surveyor/helpers/surveyor_helper_methods.rb +103 -0
  163. data/lib/surveyor/models/answer_methods.rb +86 -0
  164. data/lib/surveyor/models/dependency_condition_methods.rb +72 -0
  165. data/lib/surveyor/models/dependency_methods.rb +60 -0
  166. data/lib/surveyor/models/question_group_methods.rb +61 -0
  167. data/lib/surveyor/models/question_methods.rb +115 -0
  168. data/lib/surveyor/models/response_methods.rb +132 -0
  169. data/lib/surveyor/models/response_set_methods.rb +196 -0
  170. data/lib/surveyor/models/survey_methods.rb +103 -0
  171. data/lib/surveyor/models/survey_section_methods.rb +56 -0
  172. data/lib/surveyor/models/survey_translation_methods.rb +33 -0
  173. data/lib/surveyor/models/validation_condition_methods.rb +56 -0
  174. data/lib/surveyor/models/validation_methods.rb +48 -0
  175. data/lib/surveyor/mustache_context.rb +11 -0
  176. data/lib/surveyor/parser.rb +428 -0
  177. data/lib/surveyor/redcap_parser.rb +289 -0
  178. data/lib/surveyor/surveyor_controller_methods.rb +237 -0
  179. data/lib/surveyor/unparser.rb +147 -0
  180. data/lib/surveyor/version.rb +3 -0
  181. data/lib/surveyor.rb +13 -0
  182. data/lib/tasks/surveyor_tasks.rake +88 -0
  183. data/rails/init.rb +1 -0
  184. data/spec/controllers/surveyor_controller_spec.rb +307 -0
  185. data/spec/factories.rb +161 -0
  186. data/spec/helpers/formtastic_custom_input_spec.rb +15 -0
  187. data/spec/helpers/surveyor_helper_spec.rb +118 -0
  188. data/spec/lib/benchmark_spec.rb +22 -0
  189. data/spec/lib/chinese_survey.rb +14 -0
  190. data/spec/lib/common_spec.rb +34 -0
  191. data/spec/lib/parser_spec.rb +204 -0
  192. data/spec/lib/rake_kitchen_sink.rb +40 -0
  193. data/spec/lib/redcap_parser_spec.rb +75 -0
  194. data/spec/lib/tasks_spec.rake +26 -0
  195. data/spec/lib/unparser_spec.rb +126 -0
  196. data/spec/models/answer_spec.rb +175 -0
  197. data/spec/models/dependency_condition_spec.rb +439 -0
  198. data/spec/models/dependency_spec.rb +101 -0
  199. data/spec/models/question_group_spec.rb +93 -0
  200. data/spec/models/question_spec.rb +207 -0
  201. data/spec/models/response_set_spec.rb +477 -0
  202. data/spec/models/response_spec.rb +218 -0
  203. data/spec/models/survey_section_spec.rb +85 -0
  204. data/spec/models/survey_spec.rb +191 -0
  205. data/spec/models/validation_condition_spec.rb +113 -0
  206. data/spec/models/validation_spec.rb +74 -0
  207. data/spec/rcov.opts +2 -0
  208. data/spec/spec.opts +4 -0
  209. data/spec/spec_helper.rb +56 -0
  210. data/stacktests.sh +65 -0
  211. data/surveyor.gemspec +45 -0
  212. metadata +657 -0
@@ -0,0 +1,52 @@
1
+ == SurveyorController
2
+
3
+ The SurveyorController class just includes actions from Surveyor::SurveyorControllerMethods module. You may include your own module, and overwrite the methods or add to them using "super". A template for this customization is in your app/controllers/surveyor\_controller.rb. SurveyorController is "unloadable", so changes in development (and any environment that does not cache classes) will be reflected immediately without restarting the app.
4
+
5
+ == Models
6
+
7
+ Surveyor's models can all be customized:
8
+
9
+ - answer
10
+ - dependency_condition
11
+ - dependency
12
+ - question_group
13
+ - question
14
+ - response_set
15
+ - response
16
+ - survey_section
17
+ - survey
18
+ - validation_condition
19
+ - validation
20
+
21
+ For example, create app/models/survey.rb with the following contents:
22
+
23
+ class Survey < ActiveRecord::Base
24
+ include Surveyor::Models::SurveyMethods
25
+ def title
26
+ "Custom #{super}"
27
+ end
28
+ end
29
+
30
+ == SurveyorHelper
31
+
32
+ The SurveyorHelper module can be customized just like the models:
33
+
34
+ module SurveyorHelper
35
+ include Surveyor::Helpers::SurveyorHelperMethods
36
+ def rc_to_as(type_sym)
37
+ case type_sym.to_s
38
+ when /(integer|float)/ then :string
39
+ when /(datetime)/ then :string
40
+ when /^date$/ then :string
41
+ else type_sym
42
+ end
43
+ end
44
+ end
45
+
46
+ == Views
47
+
48
+ Surveyor's views can be overwritten by simply creating views in app/views/surveyor
49
+
50
+ == Layout
51
+
52
+ Create a custom SurveyorController as above, and specify your custom layout in it.
@@ -0,0 +1,91 @@
1
+ == Dates, Times, and Javascript Date Picker
2
+
3
+ == Default JQuery Date Picker
4
+
5
+ By default Surveyor uses the JQuery-UI date picker (http://jqueryui.com/demos/datepicker/)
6
+ for all date and time fields (denoted by :date, :time, or :datetime for the answer in the survey).
7
+
8
+ == Using Rails Date Helpers
9
+
10
+ It is possible (and relatively easy) to use the default Rails
11
+ date helpers (http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html)
12
+ instead of the javascript date picker.
13
+
14
+ To do so you would need to override two methods in the SurveyorHelperMethods. Currently the
15
+ rc_to_attr and rc_to_as handle how the form fields are displayed. The formtastic input method
16
+ (https://github.com/justinfrench/formtastic) used in the _answer.html.haml partial
17
+ calls the rc_to_attr method to get the attribute for the answer object
18
+ and then calls the rc_to_as method to get the value to set the :as parameter.
19
+
20
+ ff.input rc_to_attr(a.response_class), :as => rc_to_as(a.response_class)
21
+
22
+ def rc_to_attr(type_sym)
23
+ case type_sym.to_s
24
+ when /^answer$/ then :answer_id
25
+ else "#{type_sym.to_s}_value".to_sym
26
+ end
27
+ end
28
+
29
+ def rc_to_as(type_sym)
30
+ case type_sym.to_s
31
+ when /(integer|float|date|time|datetime)/ then :string
32
+ else type_sym
33
+ end
34
+ end
35
+
36
+ First, we would need to set that the attribute to be used is the :datetime_value attribute on the
37
+ answer. (By default we use the custom date_value and time_value methods which wrap the :datetime_value
38
+ on the answer to work with the string representation of those values). To do this we would need to
39
+ change the rc_to_attr method so that either the date or time types return the :datetime_value attribute
40
+
41
+ def rc_to_attr(type_sym)
42
+ case type_sym.to_s
43
+ when /^date|time$/ then :datetime_value
44
+ when /^(string|text|integer|float|datetime)$/ then "#{type_sym.to_s}_value".to_sym
45
+ else :answer_id
46
+ end
47
+ end
48
+
49
+
50
+ Second, we would need to update the rc_to_as method so that the date, time, and/or datetime
51
+ answer types would return those values rather than string as they do by default
52
+
53
+ def rc_to_as(type_sym)
54
+ case type_sym.to_s
55
+ when /(integer|float)/ then :string
56
+ else type_sym
57
+ end
58
+ end
59
+
60
+ Of course, you could mix and match which attribute types could be show with the Rails Date Helper
61
+ methods and which ones could use the javascript date picker.
62
+
63
+ == JQuery Tools Date Input
64
+
65
+ If you would like to use JQuery Tools dateinput instead (http://jquerytools.org/demos/dateinput/index.html)
66
+ you would need to edit the
67
+ vendor/assets/javascripts/surveyor/jquery.surveyor.js file.
68
+
69
+ Replace the jquery-ui datepicker lines:
70
+
71
+ jQuery("input[type='text'].date").datepicker({
72
+ dateFormat: 'yy-mm-dd',
73
+ changeMonth: true,
74
+ changeYear: true
75
+ });
76
+
77
+ with those for the jquery tools dateinput
78
+
79
+ jQuery('li input.date').dateinput({
80
+ format: 'dd mmm yyyy'
81
+ });
82
+
83
+ (note that you may need to add the following to make the jquery tools dateinput widget to work properly)
84
+
85
+ jQuery('li.date input').change(function(){
86
+ if ( $(this).data('dateinput') ) {
87
+ var date_obj = $(this).data('dateinput').getValue();
88
+ this.value = date_obj.getFullYear() + "-" + (date_obj.getMonth()+1) + "-" +
89
+ date_obj.getDate() + " 00:00:00 UTC";
90
+ }
91
+ });
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+ survey "Date Survey" do
3
+
4
+ section "Simple date questions" do
5
+
6
+ q "What is your birth date?"
7
+ a :date
8
+
9
+ q "At what time were you born?"
10
+ a :time
11
+
12
+ q "When would you like to schedule your next appointment?"
13
+ a :datetime
14
+
15
+ end
16
+ end
@@ -0,0 +1,284 @@
1
+ # encoding: UTF-8
2
+ # Question#is_mandatory is now false by default. The default_mandatory option allows you to set
3
+ # is_mandatory for all questions in a survey.
4
+ survey "Kitchen Sink survey", :default_mandatory => false do
5
+
6
+ section "Basic questions" do
7
+ # A label is a question that accepts no answers
8
+ label "These questions are examples of the basic supported input types"
9
+
10
+ # A basic question with radio buttons
11
+ question "What is your favorite color?", :pick => :one
12
+ answer "red"
13
+ answer "blue"
14
+ answer "green"
15
+ answer "yellow"
16
+ answer :other
17
+
18
+ # A basic question with checkboxes
19
+ # The "question" and "answer" methods may be abbreviated as "q" and "a".
20
+ # Append a reference identifier (a short string used for dependencies and validations) using the "_" underscore.
21
+ # Question reference identifiers must be unique within a survey.
22
+ # Answer reference identifiers must be unique within a question
23
+ q_2 "Choose the colors you don't like", :pick => :any
24
+ a_1 "red"
25
+ a_2 "blue"
26
+ a_3 "green"
27
+ a_4 "yellow"
28
+ a :omit
29
+
30
+ # A dependent question, with conditions and rule to logically join them
31
+ # If the conditions, logically joined into the rule, are met, then the question will be shown.
32
+ q_2a "Please explain why you don't like this color?"
33
+ a_1 "explanation", :text, :help_text => "Please give an explanation for each color you don't like"
34
+ dependency :rule => "A or B or C or D"
35
+ condition_A :q_2, "==", :a_1
36
+ condition_B :q_2, "==", :a_2
37
+ condition_C :q_2, "==", :a_3
38
+ condition_D :q_2, "==", :a_4
39
+
40
+ # The count operator checks how many responses exist for the referenced question.
41
+ # It understands conditions of the form: count== count!= count> count< count>= count<=
42
+ q_2b "Please explain why you dislike so many colors?"
43
+ a_1 "explanation", :text
44
+ dependency :rule => "Z"
45
+ condition_Z :q_2, "count>2"
46
+
47
+ # When :pick isn't specified, the default is :none (no checkbox or radio button)
48
+ q_montypython3 "What... is your name? (e.g. It is 'Arthur', King of the Britons)"
49
+ a_1 :string
50
+
51
+ # Dependency conditions can refer to any value, not just answer_id. An answer_reference still needs to be specified, to know which answer you would like to check
52
+ q_montypython4 "What... is your quest? (e.g. To seek the Holy Grail)"
53
+ a_1 :string
54
+ dependency :rule => "A"
55
+ condition_A :q_montypython3, "==", {:string_value => "It is 'Arthur', King of the Britons", :answer_reference => "1"}
56
+
57
+ # http://www.imdb.com/title/tt0071853/quotes
58
+ q_montypython5 "What... is the air-speed velocity of an unladen swallow? (e.g. What do you mean? An African or European swallow?)"
59
+ a_1 :string
60
+ dependency :rule => "A"
61
+ condition_A :q_montypython4, "==", {:string_value => "To seek the Holy Grail", :answer_reference => "1"}
62
+
63
+ label "Huh? I-- I don't know that! Auuuuuuuugh!"
64
+ dependency :rule => "A"
65
+ condition_A :q_montypython5, "==", {:string_value => "What do you mean? An African or European swallow?", :answer_reference => "1"}
66
+
67
+ q_cooling_1 "How do you cool your home?", :pick => :one
68
+ a_1 "Fans"
69
+ a_2 "Window AC"
70
+ a_3 "Central AC"
71
+ a_4 "Passive"
72
+
73
+ # When using !=, also use count>0 if you want to make sure the user responds
74
+ q_cooling_2 "How much does it cost to run your non-passive cooling solutions? (This question hidden until you respond 'How do you cool your home?')"
75
+ dependency :rule => "A and B"
76
+ condition_A :q_cooling_1, "!=", :a_4
77
+ condition_B :q_cooling_1, "count>0"
78
+ a_1 "$", :float
79
+
80
+ # Using != alone means the dependent question is shown by default
81
+ label "Please consider passive cooling solutions (This question always shown, unless you respond 'Passive')"
82
+ dependency :rule => "A"
83
+ condition_A :q_cooling_1, "!=", :a_4
84
+
85
+ # Surveys, sections, questions, groups, and answers all take the following reference arguments
86
+ # :reference_identifier # used for parsing references, usually derived from the paper version
87
+ # :data_export_identifier # used for data export
88
+ # :common_namespace # maping to a common vocabulary - the namespace
89
+ # :common_identifier # maping to a common vocabulary - the identifier within the namespace
90
+ q "Get me started on an improv sketch", :reference_identifier => "improv_start", :data_export_identifier => "i_s", :common_namespace => "sketch comedy questions", :common_identifier => "get me started"
91
+ a "who", :string
92
+ a "what", :string
93
+ a "where", :string
94
+
95
+ # Various types of responses can be accepted, and validated
96
+ q "How many pets do you own?"
97
+ a :integer
98
+ validation :rule => "A"
99
+ condition_A ">=", :integer_value => 0
100
+
101
+ # Surveys, sections, questions, groups, and answers also take a custom css class for covenience in custom styling
102
+ q "What is your address?", :custom_class => 'address'
103
+ a :text, :custom_class => 'mapper'
104
+ # validations can use regexp values
105
+ validation :rule => "A"
106
+ condition_A "=~", :regexp => "[0-9a-zA-z\. #]"
107
+
108
+ # Questions, groups, and answers take a custom renderer (a partial in the application's views dir)
109
+ # defaults are "/partials/question_group", "/partials/question", "/partials/answer", so the custom renderers should have a different name
110
+ q "Pick your favorite date AND time" #, :custom_renderer => "/partials/custom_question"
111
+ a :datetime
112
+
113
+ q_time_lunch "What time do you usually take a lunch break?"
114
+ a_1 :time
115
+
116
+ q "When would you like to meet for dinner?"
117
+ a :date
118
+
119
+ # Sliders deprecate to select boxes when javascript is off
120
+ # Valid Ruby code may be used to shorten repetitive tasks
121
+ q "Adjust the slider to reflect your level of awesomeness", :pick => :one, :display_type => :slider
122
+ (1..10).to_a.each{|num| a num.to_s}
123
+
124
+ q "How much do you like Ruby?", :pick => :one, :display_type => :slider
125
+ ["not at all", "a little", "some", "a lot", "a ton"].each{|level| a level}
126
+
127
+ # The "|" pipe is used to place labels before or after the input elements
128
+ q "How much money do you want?"
129
+ a "$|USD", :float
130
+
131
+ # Questions may be grouped
132
+ group "How much oil do you use per day?", :display_type => :inline do
133
+ q "Quantity"
134
+ a :float
135
+
136
+ q "Unit", :pick => :one, :display_type => :dropdown
137
+ a "Barrels"
138
+ a "Gallons"
139
+ a "Quarts"
140
+ end
141
+
142
+ q "Choose your Illinois county", :pick => :one, :display_type => :dropdown
143
+ ["Adams","Alexander","Bond", "Boone",
144
+ "Brown","Bureau","Calhoun","Carroll","Cass",
145
+ "Champaign", "Christian", "Clark","Clay",
146
+ "Clinton", "Coles", "Cook", "Crawford","Cumberland","DeKalb",
147
+ "De Witt","Douglas","DuPage","Edgar", "Edwards",
148
+ "Effingham","Fayette", "Ford","Franklin","Fulton",
149
+ "Gallatin","Greene", "Grundy", "Hamilton","Hancock",
150
+ "Hardin","Henderson","Henry","Iroquois","Jackson",
151
+ "Jasper", "Jefferson","Jersey","Jo Daviess","Johnson",
152
+ "Kane","Kankakee","Kendall","Knox", "La Salle",
153
+ "Lake", "Lawrence", "Lee","Livingston","Logan",
154
+ "Macon","Macoupin","Madison","Marion","Marshall", "Mason",
155
+ "Massac","McDonough","McHenry","McLean","Menard",
156
+ "Mercer","Monroe", "Montgomery","Morgan","Moultrie",
157
+ "Ogle","Peoria","Perry","Piatt","Pike","Pope",
158
+ "Pulaski","Putnam","Randolph","Richland","Rock Island",
159
+ "Saline","Sangamon","Schuyler","Scott","Shelby",
160
+ "St. Clair","Stark", "Stephenson","Tazewell","Union",
161
+ "Vermilion","Wabash","Warren","Washington","Wayne",
162
+ "White","Whiteside","Will","Williamson","Winnebago","Woodford"].each{ |county| a county}
163
+
164
+ # When an is_exclusive answer is checked, it unchecks all other options and disables them (using Javascript)
165
+ q "Choose your favorite meats", :display_type => :inline, :pick => :any
166
+ a "Chicken"
167
+ a "Pork"
168
+ a "Beef"
169
+ a "Shellfish"
170
+ a "Fish"
171
+ a "I don't eat meats!!!", :is_exclusive => true
172
+
173
+ q "All out of ideas for questions?", :pick => :one, :display_type => :inline
174
+ a "yes"
175
+ a "maybe"
176
+ a "no"
177
+ a "I don't know"
178
+
179
+ # Questions may also have input masks with fancy placeholders
180
+ q "What is your phone number?"
181
+ a :string, :input_mask => '(999)999-9999', :input_mask_placeholder => '#'
182
+
183
+ end
184
+
185
+ section "Complicated questions" do
186
+
187
+ # Grids are useful for repeated questions with the same set of answers, which are specified before the questions
188
+ grid "Tell us how often do you cover these each day" do
189
+ a "1"
190
+ a "2"
191
+ a "3"
192
+ q "Head", :pick => :one
193
+ q "Knees", :pick => :one
194
+ q "Toes", :pick => :one
195
+ end
196
+
197
+ # "grid" is a shortcut for group with :display_type => :grid
198
+ # The answers will be repeated every 10 rows, but long grids aren't recommended as they are generally tedious
199
+ grid "Tell us how you feel today day" do
200
+ a "-2"
201
+ a "-1"
202
+ a "0"
203
+ a "1"
204
+ a "2"
205
+ q "down|up" , :pick => :one
206
+ q "sad|happy", :pick => :one
207
+ q "limp|perky", :pick => :one
208
+ end
209
+
210
+ grid "For each of the car types checked, what type of options would you prefer?" do
211
+ a "Leather seats"
212
+ a "Shiny rims"
213
+ a "Subwoofer"
214
+ a "Sunroof"
215
+ a "Turbocharger"
216
+ q "SUV", :pick => :any
217
+ q "Sedan", :pick => :any
218
+ q "Coupe", :pick => :any
219
+ q "Convertible", :pick => :any
220
+ q "Minivan", :pick => :any
221
+ q "Crossover", :pick => :any
222
+ q "Wagon", :pick => :any
223
+ q "Other", :pick => :any
224
+ end
225
+
226
+ q "Please rank the following foods based on how much you like them"
227
+ a "|pizza", :integer
228
+ a "|salad", :integer
229
+ a "|sushi", :integer
230
+ a "|ice cream", :integer
231
+ a "|breakfast ceral", :integer
232
+
233
+ # :other, :string allows someone to specify both the "other" and some other information
234
+ q "Choose your favorite utensils and enter frequency of use (daily, weekly, monthly, etc...)", :pick => :any
235
+ a "spoon", :string
236
+ a "fork", :string
237
+ a "knife", :string
238
+ a :other, :string
239
+
240
+ q "What is your birth date?", :pick => :one
241
+ a "I was born on", :date
242
+ a "Refused"
243
+
244
+ q "At what time were you born?", :pick => :any
245
+ a "I was born at", :time
246
+ a "This time is approximate"
247
+
248
+ q "When would you like to schedule your next appointment?"
249
+ a :datetime
250
+
251
+ q_car "Do you own a car?", :pick => :one
252
+ a_y "Yes"
253
+ a_n "No"
254
+
255
+ # Repeaters allow multiple responses to a question or set of questions
256
+ repeater "Tell us about the cars you own" do
257
+ dependency :rule => "A"
258
+ condition_A :q_car, "==", :a_y
259
+ q "Make", :pick => :one, :display_type => :dropdown
260
+ a "Toyota"
261
+ a "Ford"
262
+ a "GMChevy"
263
+ a "Ferrari"
264
+ a "Tesla"
265
+ a "Honda"
266
+ a "Other weak brand"
267
+ q "Model"
268
+ a :string
269
+ q "Year"
270
+ a :string
271
+ end
272
+
273
+ repeater "Tell us the name and age of your siblings" do
274
+ q "Sibling"
275
+ a "Name", :string
276
+ a "Age|years", :integer
277
+ end
278
+
279
+ # File responses (uses paperclip), display_type must equal :file and answer must be :file
280
+ question "File Upload", :display_type => :file
281
+ answer :file
282
+
283
+ end
284
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: UTF-8
2
+ survey "One language is never enough" do
3
+ translations :en =>:default, :es => "translations/languages.es.yml", :he => "translations/languages.he.yml", :ko => "translations/languages.ko.yml"
4
+ section_one "One" do
5
+ g_hello "Hello" do
6
+ q_name "What is your name?"
7
+ a_name :string, :help_text => "My name is..."
8
+ end
9
+ end
10
+ section_two "Two" do
11
+ q_color "What is your favorite color?"
12
+ a_name :string
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: UTF-8
2
+ survey "Favorites" do
3
+ section "Foods" do
4
+ # In a quiz, both the questions and the answers need to have reference identifiers
5
+ # Here, the question has reference_identifier: "1", and the answers: "oint", "tweet", and "moo"
6
+ question_1 "What is the best meat?", :pick => :one, :correct => "oink"
7
+ a_oink "bacon"
8
+ a_tweet "chicken"
9
+ a_moo "beef"
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+ title: "Un idioma nunca es suficiente"
3
+ survey_sections:
4
+ one:
5
+ title: "Uno"
6
+ two:
7
+ title: "Dos"
8
+ question_groups:
9
+ hello:
10
+ text: "¡Hola!"
11
+ questions:
12
+ name:
13
+ text: "¿Cómo se llama Usted?"
14
+ answers:
15
+ name:
16
+ help_text: "Mi nombre es..."
17
+ color:
18
+ text: "¿Cuál es tu color favorito?"
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+ title: "ידיעת שפה אחת אינה מספיקה"
3
+ survey_sections:
4
+ one:
5
+ title: "אחת"
6
+ two:
7
+ title: "שנים"
8
+ question_groups:
9
+ hello:
10
+ text: "שלום"
11
+ questions:
12
+ name:
13
+ text: "מה שמך?"
14
+ answers:
15
+ name:
16
+ help_text: "שמי..."
17
+ color:
18
+ text: "מהו הצבע האהוב עליך?"
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+ title: "한가지 언어로는 충분치 않습니다."
3
+ survey_sections:
4
+ one:
5
+ title: "하나"
6
+ two:
7
+ title: "두"
8
+ question_groups:
9
+ hello:
10
+ text: "안녕하십니까"
11
+ questions:
12
+ name:
13
+ text: "성함이 어떻게 되십니까?"
14
+ answers:
15
+ name:
16
+ help_text: "제 이름은 ... 입니다"
17
+ color:
18
+ text: "좋아하는 색은 무엇입니까?"
@@ -0,0 +1,5 @@
1
+ /* Add custom styles here. They will be
2
+ * loaded after the surveyor stylesheets */
3
+
4
+ #surveyor
5
+ :font-family "Century Gothic"
@@ -0,0 +1,17 @@
1
+ module Surveyor
2
+ module ActsAsResponse
3
+ # Returns the response as a particular response_class type
4
+ def as(type_symbol)
5
+ return case type_symbol.to_sym
6
+ when :string, :text, :integer, :float, :datetime
7
+ self.send("#{type_symbol}_value".to_sym)
8
+ when :date
9
+ self.datetime_value.nil? ? nil : self.datetime_value.to_date
10
+ when :time
11
+ self.datetime_value.nil? ? nil : self.datetime_value.to_time
12
+ else # :answer_id
13
+ self.answer_id
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,59 @@
1
+ require 'securerandom'
2
+ require 'uuidtools'
3
+
4
+ module Surveyor
5
+ class Common
6
+ OPERATORS = %w(== != < > <= >= =~)
7
+
8
+ class << self
9
+ if SecureRandom.respond_to?(:urlsafe_base64)
10
+ def make_tiny_code
11
+ # 7 random bytes is increased to ~10 characters (sans padding) by
12
+ # base64 encoding
13
+ SecureRandom.urlsafe_base64(7)
14
+ end
15
+ else
16
+ def make_tiny_code
17
+ s = [SecureRandom.random_bytes(7)].pack("m*")
18
+ s.delete!("\n")
19
+ s.tr!("+/", "-_")
20
+ s.delete!("=")
21
+ end
22
+ end
23
+
24
+ def to_normalized_string(text)
25
+ words_to_omit = %w(a be but has have in is it of on or the to when)
26
+ col_text = text.to_s.gsub(/(<[^>]*>)|\n|\t/su, ' ') # Remove html tags
27
+ col_text.downcase! # Remove capitalization
28
+ col_text.gsub!(/\"|\'/u, '') # Remove potential problem characters
29
+ col_text.gsub!(/\(.*?\)/u,'') # Remove text inside parens
30
+ col_text.gsub!(/\W/u, ' ') # Remove all other non-word characters
31
+ cols = (col_text.split(' ') - words_to_omit)
32
+ (cols.size > 5 ? cols[-5..-1] : cols).join("_")
33
+ end
34
+
35
+ alias :normalize :to_normalized_string
36
+
37
+ def generate_api_id
38
+ UUIDTools::UUID.random_create.to_s
39
+ end
40
+
41
+ ##
42
+ # @private Intended for internal use only.
43
+ #
44
+ # Loads and uses either `FasterCSV` (for Ruby 1.8) or the stdlib `CSV`
45
+ # (for Ruby 1.9+).
46
+ #
47
+ # @return [Class] either `CSV` for `FasterCSV`.
48
+ def csv_impl
49
+ @csv_impl ||= if RUBY_VERSION < '1.9'
50
+ require 'fastercsv'
51
+ FasterCSV
52
+ else
53
+ require 'csv'
54
+ CSV
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,10 @@
1
+ require 'rails'
2
+ require 'surveyor'
3
+ require 'haml' # required for view resolution
4
+
5
+ module Surveyor
6
+ class Engine < Rails::Engine
7
+ root = File.expand_path('../../', __FILE__)
8
+ config.autoload_paths << root
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ module Surveyor
2
+ module Helpers
3
+ module AssetPipeline
4
+ ##
5
+ # Returns whether or not the asset pipeline is present and enabled.
6
+ #
7
+ # The detection scheme used here was ripped from jquery-rails.
8
+ def asset_pipeline_enabled?
9
+ ::Rails.version >= "3.1" && ::Rails.application.config.assets.enabled
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Surveyor
2
+ module Helpers
3
+ module FormtasticCustomInput
4
+ def input_html_options_with(choice, response_class)
5
+ input_html_options.merge(choice_html_options(choice)).merge({:id => (input_html_options[:id] || "answer_id").gsub("answer_id", response_class_to_method(response_class).to_s), :class => [input_html_options[:class], response_class].join(" ")})
6
+ end
7
+ def response_class_to_method(type_sym)
8
+ # doesn't handle response_class == answer, and doesn't have to
9
+ "#{type_sym.to_s}_value".to_sym
10
+ end
11
+ end
12
+ end
13
+ end