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.
- checksums.yaml +7 -0
- data/.gitignore +28 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +198 -0
- data/Gemfile +5 -0
- data/Gemfile.rails_version +27 -0
- data/MIT-LICENSE +20 -0
- data/README.md +166 -0
- data/Rakefile +106 -0
- data/app/controllers/surveyor_controller.rb +5 -0
- data/app/helpers/results_helper.rb +20 -0
- data/app/helpers/survey_form_builder.rb +37 -0
- data/app/helpers/surveyor_helper.rb +3 -0
- data/app/inputs/quiet_input.rb +5 -0
- data/app/inputs/surveyor_check_boxes_input.rb +35 -0
- data/app/inputs/surveyor_radio_input.rb +18 -0
- data/app/models/answer.rb +3 -0
- data/app/models/dependency.rb +3 -0
- data/app/models/dependency_condition.rb +3 -0
- data/app/models/question.rb +3 -0
- data/app/models/question_group.rb +4 -0
- data/app/models/response.rb +4 -0
- data/app/models/response_set.rb +3 -0
- data/app/models/survey.rb +3 -0
- data/app/models/survey_section.rb +4 -0
- data/app/models/survey_section_sweeper.rb +15 -0
- data/app/models/survey_translation.rb +4 -0
- data/app/models/validation.rb +3 -0
- data/app/models/validation_condition.rb +3 -0
- data/app/views/layouts/results.html.erb +13 -0
- data/app/views/layouts/surveyor_default.html.erb +12 -0
- data/app/views/partials/_answer.html.haml +25 -0
- data/app/views/partials/_dependents.html.haml +5 -0
- data/app/views/partials/_question.html.haml +28 -0
- data/app/views/partials/_question_group.html.haml +44 -0
- data/app/views/partials/_section.html.haml +12 -0
- data/app/views/partials/_section_menu.html.haml +12 -0
- data/app/views/surveyor/edit.html.haml +24 -0
- data/app/views/surveyor/export.json.rabl +85 -0
- data/app/views/surveyor/new.html.haml +24 -0
- data/app/views/surveyor/show.html.haml +74 -0
- data/app/views/surveyor/show.json.rabl +15 -0
- data/ci-exec.sh +56 -0
- data/config/routes.rb +8 -0
- data/cucumber.yml +10 -0
- data/doc/REPRESENTATIONS.md +34 -0
- data/doc/api_id_schema.json +7 -0
- data/doc/question types.png +0 -0
- data/doc/response_set_schema.json +54 -0
- data/doc/surveyor question combinations.png +0 -0
- data/doc/surveyor reject or delete decision matrix.png +0 -0
- data/doc/surveyor_models.png +0 -0
- data/doc/surveyor_models2.png +0 -0
- data/doc/surveyor_timestamp_schema.json +9 -0
- data/features/ajax_submissions.feature +140 -0
- data/features/export_to_json.feature +344 -0
- data/features/internationalization.feature +121 -0
- data/features/no_duplicates.feature +110 -0
- data/features/show_survey.feature +71 -0
- data/features/step_definitions/parser_steps.rb +145 -0
- data/features/step_definitions/surveyor_steps.rb +325 -0
- data/features/step_definitions/ui_steps.rb +25 -0
- data/features/step_definitions/web_steps.rb +225 -0
- data/features/support/REDCapDemoDatabase_DataDictionary.csv +127 -0
- data/features/support/database_cleaner.rb +16 -0
- data/features/support/env.rb +56 -0
- data/features/support/hooks.rb +4 -0
- data/features/support/paths.rb +39 -0
- data/features/support/redcap_new_headers.csv +1 -0
- data/features/support/redcap_siblings.csv +1 -0
- data/features/support/redcap_whitespace.csv +1 -0
- data/features/support/selectors.rb +39 -0
- data/features/support/simultaneous_ajax.rb +101 -0
- data/features/support/single_quit_selenium_driver.rb +23 -0
- data/features/support/slow_updates.rb +18 -0
- data/features/surveyor.feature +895 -0
- data/features/surveyor_dependencies.feature +476 -0
- data/features/surveyor_parser.feature +504 -0
- data/features/z_redcap_parser.feature +62 -0
- data/lib/assets/images/surveyor/next.gif +0 -0
- data/lib/assets/images/surveyor/prev.gif +0 -0
- data/lib/assets/images/surveyor/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/lib/assets/images/surveyor/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/lib/assets/images/surveyor/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/lib/assets/images/surveyor/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/lib/assets/images/surveyor/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/lib/assets/images/surveyor/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/lib/assets/images/surveyor/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/lib/assets/images/surveyor/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/lib/assets/images/surveyor/ui-icons_222222_256x240.png +0 -0
- data/lib/assets/images/surveyor/ui-icons_2e83ff_256x240.png +0 -0
- data/lib/assets/images/surveyor/ui-icons_454545_256x240.png +0 -0
- data/lib/assets/images/surveyor/ui-icons_888888_256x240.png +0 -0
- data/lib/assets/images/surveyor/ui-icons_cd0a0a_256x240.png +0 -0
- data/lib/assets/javascripts/surveyor/jquery-1.9.0.js +9555 -0
- data/lib/assets/javascripts/surveyor/jquery-ui-1.10.0.custom.js +14850 -0
- data/lib/assets/javascripts/surveyor/jquery-ui-timepicker-addon.js +1919 -0
- data/lib/assets/javascripts/surveyor/jquery.maskedinput.js +338 -0
- data/lib/assets/javascripts/surveyor/jquery.selectToUISlider.js +240 -0
- data/lib/assets/javascripts/surveyor/jquery.surveyor.js +154 -0
- data/lib/assets/stylesheets/surveyor.sass +132 -0
- data/lib/assets/stylesheets/surveyor/jquery-ui-1.10.0.custom.css +1174 -0
- data/lib/assets/stylesheets/surveyor/jquery-ui-timepicker-addon.css +11 -0
- data/lib/assets/stylesheets/surveyor/reset.css +48 -0
- data/lib/assets/stylesheets/surveyor/results.css +125 -0
- data/lib/assets/stylesheets/surveyor/ui.slider.extras.css +110 -0
- data/lib/generators/surveyor/custom_generator.rb +18 -0
- data/lib/generators/surveyor/install_generator.rb +101 -0
- data/lib/generators/surveyor/templates/app/assets/javascripts/surveyor_all.js +6 -0
- data/lib/generators/surveyor/templates/app/assets/stylesheets/surveyor_all.css +9 -0
- data/lib/generators/surveyor/templates/app/controllers/surveyor_controller.rb +40 -0
- data/lib/generators/surveyor/templates/app/views/layouts/surveyor_custom.html.erb +13 -0
- data/lib/generators/surveyor/templates/config/locales/surveyor_en.yml +19 -0
- data/lib/generators/surveyor/templates/config/locales/surveyor_es.yml +19 -0
- data/lib/generators/surveyor/templates/config/locales/surveyor_he.yml +19 -0
- data/lib/generators/surveyor/templates/config/locales/surveyor_ko.yml +19 -0
- data/lib/generators/surveyor/templates/db/migrate/add_api_id_to_question_groups.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/add_api_ids.rb +14 -0
- data/lib/generators/surveyor/templates/db/migrate/add_api_ids_to_response_sets_and_responses.rb +12 -0
- data/lib/generators/surveyor/templates/db/migrate/add_correct_answer_id_to_questions.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/add_default_value_to_answers.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/add_display_order_to_surveys.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/add_display_type_to_answers.rb +14 -0
- data/lib/generators/surveyor/templates/db/migrate/add_index_to_response_sets.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/add_index_to_surveys.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/add_input_mask_attributes_to_answer.rb +12 -0
- data/lib/generators/surveyor/templates/db/migrate/add_section_id_to_responses.rb +12 -0
- data/lib/generators/surveyor/templates/db/migrate/add_unique_index_on_access_code_and_version_in_surveys.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/add_unique_indicies.rb +18 -0
- data/lib/generators/surveyor/templates/db/migrate/add_version_to_surveys.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/api_ids_must_be_unique.rb +23 -0
- data/lib/generators/surveyor/templates/db/migrate/create_answers.rb +38 -0
- data/lib/generators/surveyor/templates/db/migrate/create_dependencies.rb +23 -0
- data/lib/generators/surveyor/templates/db/migrate/create_dependency_conditions.rb +30 -0
- data/lib/generators/surveyor/templates/db/migrate/create_question_groups.rb +28 -0
- data/lib/generators/surveyor/templates/db/migrate/create_questions.rb +37 -0
- data/lib/generators/surveyor/templates/db/migrate/create_response_sets.rb +23 -0
- data/lib/generators/surveyor/templates/db/migrate/create_responses.rb +34 -0
- data/lib/generators/surveyor/templates/db/migrate/create_survey_sections.rb +30 -0
- data/lib/generators/surveyor/templates/db/migrate/create_survey_translations.rb +19 -0
- data/lib/generators/surveyor/templates/db/migrate/create_surveys.rb +32 -0
- data/lib/generators/surveyor/templates/db/migrate/create_validation_conditions.rb +33 -0
- data/lib/generators/surveyor/templates/db/migrate/create_validations.rb +21 -0
- data/lib/generators/surveyor/templates/db/migrate/drop_unique_index_on_access_code_in_surveys.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/update_blank_api_ids_on_question_group.rb +22 -0
- data/lib/generators/surveyor/templates/db/migrate/update_blank_versions_on_surveys.rb +13 -0
- data/lib/generators/surveyor/templates/surveys/EXTENDING_SURVEYOR.md +52 -0
- data/lib/generators/surveyor/templates/surveys/MODIFYING_SURVEYOR.md +91 -0
- data/lib/generators/surveyor/templates/surveys/date_survey.rb +16 -0
- data/lib/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +280 -0
- data/lib/generators/surveyor/templates/surveys/languages.rb +14 -0
- data/lib/generators/surveyor/templates/surveys/quiz.rb +11 -0
- data/lib/generators/surveyor/templates/surveys/translations/languages.es.yml +18 -0
- data/lib/generators/surveyor/templates/surveys/translations/languages.he.yml +18 -0
- data/lib/generators/surveyor/templates/surveys/translations/languages.ko.yml +18 -0
- data/lib/generators/surveyor/templates/vendor/assets/stylesheets/custom.sass +5 -0
- data/lib/surveyor.rb +13 -0
- data/lib/surveyor/acts_as_response.rb +17 -0
- data/lib/surveyor/common.rb +59 -0
- data/lib/surveyor/engine.rb +10 -0
- data/lib/surveyor/helpers/asset_pipeline.rb +18 -0
- data/lib/surveyor/helpers/formtastic_custom_input.rb +13 -0
- data/lib/surveyor/helpers/surveyor_helper_methods.rb +103 -0
- data/lib/surveyor/models/answer_methods.rb +83 -0
- data/lib/surveyor/models/dependency_condition_methods.rb +69 -0
- data/lib/surveyor/models/dependency_methods.rb +57 -0
- data/lib/surveyor/models/question_group_methods.rb +58 -0
- data/lib/surveyor/models/question_methods.rb +112 -0
- data/lib/surveyor/models/response_methods.rb +126 -0
- data/lib/surveyor/models/response_set_methods.rb +188 -0
- data/lib/surveyor/models/survey_methods.rb +100 -0
- data/lib/surveyor/models/survey_section_methods.rb +53 -0
- data/lib/surveyor/models/survey_translation_methods.rb +30 -0
- data/lib/surveyor/models/validation_condition_methods.rb +54 -0
- data/lib/surveyor/models/validation_methods.rb +45 -0
- data/lib/surveyor/mustache_context.rb +11 -0
- data/lib/surveyor/parser.rb +427 -0
- data/lib/surveyor/redcap_parser.rb +288 -0
- data/lib/surveyor/surveyor_controller_methods.rb +236 -0
- data/lib/surveyor/unparser.rb +147 -0
- data/lib/surveyor/version.rb +3 -0
- data/lib/tasks/surveyor_tasks.rake +88 -0
- data/rails/init.rb +1 -0
- data/spec/controllers/surveyor_controller_spec.rb +311 -0
- data/spec/factories.rb +166 -0
- data/spec/helpers/formtastic_custom_input_spec.rb +15 -0
- data/spec/helpers/surveyor_helper_spec.rb +117 -0
- data/spec/lib/benchmark_spec.rb +22 -0
- data/spec/lib/chinese_survey.rb +14 -0
- data/spec/lib/common_spec.rb +34 -0
- data/spec/lib/parser_spec.rb +204 -0
- data/spec/lib/rake_kitchen_sink.rb +40 -0
- data/spec/lib/redcap_parser_spec.rb +75 -0
- data/spec/lib/tasks_spec.rake +26 -0
- data/spec/lib/unparser_spec.rb +126 -0
- data/spec/models/answer_spec.rb +174 -0
- data/spec/models/dependency_condition_spec.rb +439 -0
- data/spec/models/dependency_spec.rb +101 -0
- data/spec/models/question_group_spec.rb +93 -0
- data/spec/models/question_spec.rb +206 -0
- data/spec/models/response_set_spec.rb +477 -0
- data/spec/models/response_spec.rb +218 -0
- data/spec/models/survey_section_spec.rb +85 -0
- data/spec/models/survey_spec.rb +191 -0
- data/spec/models/validation_condition_spec.rb +113 -0
- data/spec/models/validation_spec.rb +74 -0
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +56 -0
- data/stacktests.sh +65 -0
- data/surveyor.gemspec +53 -0
- 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: "좋아하는 색은 무엇입니까?"
|
data/lib/surveyor.rb
ADDED
@@ -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,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
|
+
" You answered "#{trigger_responses.join("" and "")}" to the question "#{dependent_questions.map(&:text).join("","")}""
|
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
|