affectiva-surveyor 1.5.0.pre.disco.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (212) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +28 -0
  3. data/.rspec +1 -0
  4. data/CHANGELOG.md +198 -0
  5. data/Gemfile +5 -0
  6. data/Gemfile.rails_version +27 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.md +166 -0
  9. data/Rakefile +106 -0
  10. data/app/controllers/surveyor_controller.rb +5 -0
  11. data/app/helpers/results_helper.rb +20 -0
  12. data/app/helpers/survey_form_builder.rb +37 -0
  13. data/app/helpers/surveyor_helper.rb +3 -0
  14. data/app/inputs/quiet_input.rb +5 -0
  15. data/app/inputs/surveyor_check_boxes_input.rb +35 -0
  16. data/app/inputs/surveyor_radio_input.rb +18 -0
  17. data/app/models/answer.rb +3 -0
  18. data/app/models/dependency.rb +3 -0
  19. data/app/models/dependency_condition.rb +3 -0
  20. data/app/models/question.rb +3 -0
  21. data/app/models/question_group.rb +4 -0
  22. data/app/models/response.rb +4 -0
  23. data/app/models/response_set.rb +3 -0
  24. data/app/models/survey.rb +3 -0
  25. data/app/models/survey_section.rb +4 -0
  26. data/app/models/survey_section_sweeper.rb +15 -0
  27. data/app/models/survey_translation.rb +4 -0
  28. data/app/models/validation.rb +3 -0
  29. data/app/models/validation_condition.rb +3 -0
  30. data/app/views/layouts/results.html.erb +13 -0
  31. data/app/views/layouts/surveyor_default.html.erb +12 -0
  32. data/app/views/partials/_answer.html.haml +25 -0
  33. data/app/views/partials/_dependents.html.haml +5 -0
  34. data/app/views/partials/_question.html.haml +28 -0
  35. data/app/views/partials/_question_group.html.haml +44 -0
  36. data/app/views/partials/_section.html.haml +12 -0
  37. data/app/views/partials/_section_menu.html.haml +12 -0
  38. data/app/views/surveyor/edit.html.haml +24 -0
  39. data/app/views/surveyor/export.json.rabl +85 -0
  40. data/app/views/surveyor/new.html.haml +24 -0
  41. data/app/views/surveyor/show.html.haml +74 -0
  42. data/app/views/surveyor/show.json.rabl +15 -0
  43. data/ci-exec.sh +56 -0
  44. data/config/routes.rb +8 -0
  45. data/cucumber.yml +10 -0
  46. data/doc/REPRESENTATIONS.md +34 -0
  47. data/doc/api_id_schema.json +7 -0
  48. data/doc/question types.png +0 -0
  49. data/doc/response_set_schema.json +54 -0
  50. data/doc/surveyor question combinations.png +0 -0
  51. data/doc/surveyor reject or delete decision matrix.png +0 -0
  52. data/doc/surveyor_models.png +0 -0
  53. data/doc/surveyor_models2.png +0 -0
  54. data/doc/surveyor_timestamp_schema.json +9 -0
  55. data/features/ajax_submissions.feature +140 -0
  56. data/features/export_to_json.feature +344 -0
  57. data/features/internationalization.feature +121 -0
  58. data/features/no_duplicates.feature +110 -0
  59. data/features/show_survey.feature +71 -0
  60. data/features/step_definitions/parser_steps.rb +145 -0
  61. data/features/step_definitions/surveyor_steps.rb +325 -0
  62. data/features/step_definitions/ui_steps.rb +25 -0
  63. data/features/step_definitions/web_steps.rb +225 -0
  64. data/features/support/REDCapDemoDatabase_DataDictionary.csv +127 -0
  65. data/features/support/database_cleaner.rb +16 -0
  66. data/features/support/env.rb +56 -0
  67. data/features/support/hooks.rb +4 -0
  68. data/features/support/paths.rb +39 -0
  69. data/features/support/redcap_new_headers.csv +1 -0
  70. data/features/support/redcap_siblings.csv +1 -0
  71. data/features/support/redcap_whitespace.csv +1 -0
  72. data/features/support/selectors.rb +39 -0
  73. data/features/support/simultaneous_ajax.rb +101 -0
  74. data/features/support/single_quit_selenium_driver.rb +23 -0
  75. data/features/support/slow_updates.rb +18 -0
  76. data/features/surveyor.feature +895 -0
  77. data/features/surveyor_dependencies.feature +476 -0
  78. data/features/surveyor_parser.feature +504 -0
  79. data/features/z_redcap_parser.feature +62 -0
  80. data/lib/assets/images/surveyor/next.gif +0 -0
  81. data/lib/assets/images/surveyor/prev.gif +0 -0
  82. data/lib/assets/images/surveyor/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  83. data/lib/assets/images/surveyor/ui-bg_flat_75_ffffff_40x100.png +0 -0
  84. data/lib/assets/images/surveyor/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  85. data/lib/assets/images/surveyor/ui-bg_glass_65_ffffff_1x400.png +0 -0
  86. data/lib/assets/images/surveyor/ui-bg_glass_75_dadada_1x400.png +0 -0
  87. data/lib/assets/images/surveyor/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  88. data/lib/assets/images/surveyor/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  89. data/lib/assets/images/surveyor/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  90. data/lib/assets/images/surveyor/ui-icons_222222_256x240.png +0 -0
  91. data/lib/assets/images/surveyor/ui-icons_2e83ff_256x240.png +0 -0
  92. data/lib/assets/images/surveyor/ui-icons_454545_256x240.png +0 -0
  93. data/lib/assets/images/surveyor/ui-icons_888888_256x240.png +0 -0
  94. data/lib/assets/images/surveyor/ui-icons_cd0a0a_256x240.png +0 -0
  95. data/lib/assets/javascripts/surveyor/jquery-1.9.0.js +9555 -0
  96. data/lib/assets/javascripts/surveyor/jquery-ui-1.10.0.custom.js +14850 -0
  97. data/lib/assets/javascripts/surveyor/jquery-ui-timepicker-addon.js +1919 -0
  98. data/lib/assets/javascripts/surveyor/jquery.maskedinput.js +338 -0
  99. data/lib/assets/javascripts/surveyor/jquery.selectToUISlider.js +240 -0
  100. data/lib/assets/javascripts/surveyor/jquery.surveyor.js +154 -0
  101. data/lib/assets/stylesheets/surveyor.sass +132 -0
  102. data/lib/assets/stylesheets/surveyor/jquery-ui-1.10.0.custom.css +1174 -0
  103. data/lib/assets/stylesheets/surveyor/jquery-ui-timepicker-addon.css +11 -0
  104. data/lib/assets/stylesheets/surveyor/reset.css +48 -0
  105. data/lib/assets/stylesheets/surveyor/results.css +125 -0
  106. data/lib/assets/stylesheets/surveyor/ui.slider.extras.css +110 -0
  107. data/lib/generators/surveyor/custom_generator.rb +18 -0
  108. data/lib/generators/surveyor/install_generator.rb +101 -0
  109. data/lib/generators/surveyor/templates/app/assets/javascripts/surveyor_all.js +6 -0
  110. data/lib/generators/surveyor/templates/app/assets/stylesheets/surveyor_all.css +9 -0
  111. data/lib/generators/surveyor/templates/app/controllers/surveyor_controller.rb +40 -0
  112. data/lib/generators/surveyor/templates/app/views/layouts/surveyor_custom.html.erb +13 -0
  113. data/lib/generators/surveyor/templates/config/locales/surveyor_en.yml +19 -0
  114. data/lib/generators/surveyor/templates/config/locales/surveyor_es.yml +19 -0
  115. data/lib/generators/surveyor/templates/config/locales/surveyor_he.yml +19 -0
  116. data/lib/generators/surveyor/templates/config/locales/surveyor_ko.yml +19 -0
  117. data/lib/generators/surveyor/templates/db/migrate/add_api_id_to_question_groups.rb +10 -0
  118. data/lib/generators/surveyor/templates/db/migrate/add_api_ids.rb +14 -0
  119. data/lib/generators/surveyor/templates/db/migrate/add_api_ids_to_response_sets_and_responses.rb +12 -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 +280 -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.rb +13 -0
  158. data/lib/surveyor/acts_as_response.rb +17 -0
  159. data/lib/surveyor/common.rb +59 -0
  160. data/lib/surveyor/engine.rb +10 -0
  161. data/lib/surveyor/helpers/asset_pipeline.rb +18 -0
  162. data/lib/surveyor/helpers/formtastic_custom_input.rb +13 -0
  163. data/lib/surveyor/helpers/surveyor_helper_methods.rb +103 -0
  164. data/lib/surveyor/models/answer_methods.rb +83 -0
  165. data/lib/surveyor/models/dependency_condition_methods.rb +69 -0
  166. data/lib/surveyor/models/dependency_methods.rb +57 -0
  167. data/lib/surveyor/models/question_group_methods.rb +58 -0
  168. data/lib/surveyor/models/question_methods.rb +112 -0
  169. data/lib/surveyor/models/response_methods.rb +126 -0
  170. data/lib/surveyor/models/response_set_methods.rb +188 -0
  171. data/lib/surveyor/models/survey_methods.rb +100 -0
  172. data/lib/surveyor/models/survey_section_methods.rb +53 -0
  173. data/lib/surveyor/models/survey_translation_methods.rb +30 -0
  174. data/lib/surveyor/models/validation_condition_methods.rb +54 -0
  175. data/lib/surveyor/models/validation_methods.rb +45 -0
  176. data/lib/surveyor/mustache_context.rb +11 -0
  177. data/lib/surveyor/parser.rb +427 -0
  178. data/lib/surveyor/redcap_parser.rb +288 -0
  179. data/lib/surveyor/surveyor_controller_methods.rb +236 -0
  180. data/lib/surveyor/unparser.rb +147 -0
  181. data/lib/surveyor/version.rb +3 -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 +311 -0
  185. data/spec/factories.rb +166 -0
  186. data/spec/helpers/formtastic_custom_input_spec.rb +15 -0
  187. data/spec/helpers/surveyor_helper_spec.rb +117 -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 +174 -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 +206 -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 +53 -0
  212. metadata +601 -0
@@ -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,13 @@
1
+ module Surveyor
2
+ require 'surveyor/engine' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
3
+ autoload :VERSION, 'surveyor/version'
4
+ autoload :ParserError, 'surveyor/parser'
5
+ end
6
+ require 'surveyor/common'
7
+ require 'surveyor/acts_as_response'
8
+ # require 'surveyor/surveyor_controller_methods'
9
+ # require 'surveyor/models/survey_methods'
10
+ require 'formtastic'
11
+ Formtastic::FormBuilder.default_text_area_height = 5
12
+ Formtastic::FormBuilder.default_text_area_width = 50
13
+ Formtastic::FormBuilder.all_fields_required_by_default = false
@@ -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,18 @@
1
+ module Surveyor
2
+ module Helpers
3
+ module AssetPipeline
4
+ ##
5
+ # Returns whether or not the asset pipeline is present and enabled.
6
+ #
7
+ # With Rails4 it appears that assets.enabled is false if
8
+ # --skip-sprockets is specified when creating the application,
9
+ # but the assets.enabled option is nil in the default case
10
+ # (i.e., pipeline enabled).
11
+ def asset_pipeline_enabled?
12
+ return false unless Rails.configuration.respond_to?('assets')
13
+ assets = Rails.configuration.assets
14
+ assets.enabled.nil? || assets.enabled
15
+ end
16
+ end
17
+ end
18
+ 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
@@ -0,0 +1,103 @@
1
+ require 'surveyor/helpers/asset_pipeline'
2
+
3
+ module Surveyor
4
+ module Helpers
5
+ module SurveyorHelperMethods
6
+ include AssetPipeline
7
+
8
+ # Layout: stylsheets and javascripts
9
+ def surveyor_includes
10
+ if asset_pipeline_enabled?
11
+ stylesheet_link_tag('surveyor_all') + javascript_include_tag('surveyor_all')
12
+ else
13
+ stylesheet_link_tag('surveyor/reset',
14
+ 'surveyor/jquery-ui-1.10.0.custom',
15
+ 'surveyor/jquery-ui-timepicker-addon',
16
+ 'surveyor/ui.slider.extras',
17
+ 'surveyor/results',
18
+ 'surveyor',
19
+ 'custom') +
20
+ javascript_include_tag('surveyor/jquery-1.9.0',
21
+ 'surveyor/jquery-ui-1.10.0.custom',
22
+ 'surveyor/jquery-ui-timepicker-addon',
23
+ 'surveyor/jquery.selectToUISlider',
24
+ 'surveyor/jquery.surveyor',
25
+ 'surveyor/jquery.maskedinput')
26
+ end
27
+ end
28
+ # Helper for displaying warning/notice/error flash messages
29
+ def flash_messages(types)
30
+ types.map{|type| content_tag(:div, "#{flash[type]}".html_safe, :class => type.to_s)}.join.html_safe
31
+ end
32
+ # Section: dependencies, menu, previous and next
33
+ def dependency_explanation_helper(question,response_set)
34
+ # Attempts to explain why this dependent question needs to be answered by referenced the dependent question and users response
35
+ trigger_responses = []
36
+ dependent_questions = Question.find_all_by_id(question.dependency.dependency_conditions.map(&:question_id)).uniq
37
+ response_set.responses.find_all_by_question_id(dependent_questions.map(&:id)).uniq.each do |resp|
38
+ trigger_responses << resp.to_s
39
+ end
40
+ "&nbsp;&nbsp;You answered &quot;#{trigger_responses.join("&quot; and &quot;")}&quot; to the question &quot;#{dependent_questions.map(&:text).join("&quot;,&quot;")}&quot;"
41
+ end
42
+ def menu_button_for(section)
43
+ submit_tag(section.translation(I18n.locale)[:title], :name => "section[#{section.id}]")
44
+ end
45
+ def previous_section
46
+ # use copy in memory instead of making extra db calls
47
+ submit_tag(t('surveyor.previous_section').html_safe, :name => "section[#{@sections[@sections.index(@section)-1].id}]") unless @sections.first == @section
48
+ end
49
+ def next_section
50
+ # use copy in memory instead of making extra db calls
51
+ @sections.last == @section ? submit_tag(t('surveyor.click_here_to_finish').html_safe, :name => "finish") : submit_tag(t('surveyor.next_section').html_safe, :name => "section[#{@sections[@sections.index(@section)+1].id}]")
52
+ end
53
+
54
+ # Questions
55
+ def q_text(q, context=nil, locale=nil)
56
+ "#{next_question_number(q) unless (q.dependent? or q.display_type == "label" or q.display_type == "image" or q.part_of_group?)}#{q.text_for(nil, context, locale)}"
57
+ end
58
+
59
+ def next_question_number(question)
60
+ @n ||= 0
61
+ "<span class='qnum'>#{@n += 1}) </span>"
62
+ end
63
+
64
+ # Responses
65
+ def rc_to_attr(type_sym)
66
+ case type_sym.to_s
67
+ when /^answer$/ then :answer_id
68
+ else "#{type_sym.to_s}_value".to_sym
69
+ end
70
+ end
71
+
72
+ def rc_to_as(type_sym)
73
+ case type_sym.to_s
74
+ when /(integer|float|date|time|datetime)/ then :string
75
+ else type_sym
76
+ end
77
+ end
78
+
79
+ def generate_pick_none_input_html(value, default_value, css_class, response_class, disabled, input_mask, input_mask_placeholder)
80
+ html = {}
81
+ html[:class] = [response_class,css_class].reject{ |c| c.blank? }
82
+ html[:value] = value.blank? ? default_value : value
83
+ html[:disabled] = disabled unless disabled.blank?
84
+ if input_mask
85
+ html[:'data-input-mask'] = input_mask
86
+ html[:'data-input-mask-placeholder'] = input_mask_placeholder unless input_mask_placeholder.blank?
87
+ end
88
+ html
89
+ end
90
+
91
+ # Responses
92
+ def response_for(response_set, question, answer = nil, response_group = nil)
93
+ return nil unless response_set && question && question.id
94
+ result = response_set.responses.detect{|r| (r.question_id == question.id) && (answer.blank? ? true : r.answer_id == answer.id) && (r.response_group.blank? ? true : r.response_group.to_i == response_group.to_i)}
95
+ result.blank? ? response_set.responses.build(:question_id => question.id, :response_group => response_group) : result
96
+ end
97
+ def response_idx(increment = true)
98
+ @rc ||= 0
99
+ (increment ? @rc += 1 : @rc).to_s
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,83 @@
1
+ require 'surveyor/common'
2
+
3
+ module Surveyor
4
+ module Models
5
+ module AnswerMethods
6
+ def self.included(base)
7
+ # Associations
8
+ base.send :belongs_to, :question
9
+ base.send :has_many, :responses
10
+ base.send :has_many, :validations, :dependent => :destroy
11
+
12
+ # Scopes
13
+ base.instance_eval {default_scope ->{order "#{base.quoted_table_name}.display_order ASC"}}
14
+
15
+ # Mustache
16
+ base.send :include, MustacheContext
17
+
18
+ @@validations_already_included ||= nil
19
+ unless @@validations_already_included
20
+ # Validations
21
+ base.send :validates_presence_of, :text
22
+ # this causes issues with building and saving
23
+ # base.send :validates_numericality_of, :question_id, :allow_nil => false, :only_integer => true
24
+ @@validations_already_included = true
25
+ end
26
+ end
27
+
28
+ # Instance Methods
29
+ def initialize(*args)
30
+ super(*args)
31
+ default_args
32
+ end
33
+
34
+ def default_args
35
+ self.is_exclusive ||= false
36
+ self.display_type ||= "default"
37
+ self.response_class ||= "answer"
38
+ self.short_text ||= text
39
+ self.data_export_identifier ||= Surveyor::Common.normalize(text)
40
+ self.api_id ||= Surveyor::Common.generate_api_id
41
+ end
42
+ def display_type=(val)
43
+ write_attribute(:display_type, val.nil? ? nil : val.to_s)
44
+ end
45
+
46
+ def css_class
47
+ [(is_exclusive ? "exclusive" : nil), custom_class].compact.join(" ")
48
+ end
49
+
50
+ def text_for(position = nil, context = nil, locale = nil)
51
+ return "" if display_type == "hidden_label"
52
+ imaged(split(in_context(translation(locale)[:text], context), position))
53
+ end
54
+ def help_text_for(context = nil, locale = nil)
55
+ in_context(translation(locale)[:help_text], context)
56
+ end
57
+ def default_value_for(context = nil, locale = nil)
58
+ in_context(translation(locale)[:default_value], context)
59
+ end
60
+ def split(text, position=nil)
61
+ case position
62
+ when :pre
63
+ text.split("|",2)[0]
64
+ when :post
65
+ text.split("|",2)[1]
66
+ else
67
+ text
68
+ end.to_s
69
+ end
70
+ def translation(locale)
71
+ {:text => self.text, :help_text => self.help_text, :default_value => self.default_value}.with_indifferent_access.merge(
72
+ (self.question.translation(locale)[:answers] || {})[self.reference_identifier] || {}
73
+ )
74
+ end
75
+
76
+ private
77
+
78
+ def imaged(text)
79
+ self.display_type == "image" && !text.blank? ? ActionController::Base.helpers.image_tag(text) : text
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,69 @@
1
+ module Surveyor
2
+ module Models
3
+ module DependencyConditionMethods
4
+ def self.included(base)
5
+ # Associations
6
+ base.send :belongs_to, :answer
7
+ base.send :belongs_to, :dependency
8
+ base.send :belongs_to, :dependent_question, :foreign_key => :question_id, :class_name => :question
9
+ base.send :belongs_to, :question
10
+
11
+ @@validations_already_included ||= nil
12
+ unless @@validations_already_included
13
+ # Validations
14
+ base.send :validates_presence_of, :operator, :rule_key
15
+ base.send :validate, :validates_operator
16
+ base.send :validates_uniqueness_of, :rule_key, :scope => :dependency_id
17
+ # this causes issues with building and saving
18
+ # base.send :validates_numericality_of, :question_id, :dependency_id
19
+
20
+ @@validations_already_included = true
21
+ end
22
+
23
+ base.send :include, Surveyor::ActsAsResponse # includes "as" instance method
24
+
25
+ # Class methods
26
+ base.instance_eval do
27
+ def operators
28
+ Surveyor::Common::OPERATORS
29
+ end
30
+ end
31
+ end
32
+
33
+ # Instance methods
34
+ def to_hash(response_set)
35
+ # all responses to associated question
36
+ responses = question.blank? ? [] : response_set.responses.where("responses.answer_id in (?)", question.answer_ids)
37
+ if self.operator.match /^count(>|>=|<|<=|==|!=)\d+$/
38
+ op, i = self.operator.scan(/^count(>|>=|<|<=|==|!=)(\d+)$/).flatten
39
+ # logger.warn({rule_key.to_sym => responses.count.send(op, i.to_i)})
40
+ return {rule_key.to_sym => (op == "!=" ? !responses.count.send("==", i.to_i) : responses.count.send(op, i.to_i))}
41
+ elsif operator == "!=" and (responses.blank? or responses.none?{|r| r.answer.id == self.answer.id})
42
+ # logger.warn( {rule_key.to_sym => true})
43
+ return {rule_key.to_sym => true}
44
+ elsif response = responses.detect{|r| r.answer.id == self.answer.id}
45
+ klass = response.answer.response_class
46
+ klass = "answer" if self.as(klass).nil? # it should compare answer ids when the dependency condition *_value is nil
47
+ case self.operator
48
+ when "==", "<", ">", "<=", ">="
49
+ # logger.warn( {rule_key.to_sym => response.as(klass).send(self.operator, self.as(klass))})
50
+ return {rule_key.to_sym => !response.as(klass).nil? && response.as(klass).send(self.operator, self.as(klass))}
51
+ when "!="
52
+ # logger.warn( {rule_key.to_sym => !response.as(klass).send("==", self.as(klass))})
53
+ return {rule_key.to_sym => !response.as(klass).send("==", self.as(klass))}
54
+ end
55
+ end
56
+ # logger.warn({rule_key.to_sym => false})
57
+ {rule_key.to_sym => false}
58
+ end
59
+
60
+ protected
61
+
62
+ def validates_operator
63
+ errors.add(:operator, "Invalid operator") unless
64
+ Surveyor::Common::OPERATORS.include?(self.operator) ||
65
+ self.operator && self.operator.match(/^count(<|>|==|>=|<=|!=)(\d+)/)
66
+ end
67
+ end
68
+ end
69
+ end