surveyor_gui 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +44 -0
- data/.travis.yml +17 -0
- data/Gemfile +7 -0
- data/LICENSE +21 -0
- data/MIT-LICENSE +20 -0
- data/README.md +159 -0
- data/Rakefile +66 -0
- data/app/controllers/answers_controller.rb +3 -0
- data/app/controllers/application_controller.rb +3 -0
- data/app/controllers/dependencys_controller.rb +286 -0
- data/app/controllers/question_groups_controller.rb +84 -0
- data/app/controllers/questions_controller.rb +187 -0
- data/app/controllers/survey_sections_controller.rb +80 -0
- data/app/controllers/surveyforms_controller.rb +4 -0
- data/app/controllers/surveyor_controller.rb +89 -0
- data/app/controllers/surveyor_gui/reports_controller.rb +339 -0
- data/app/controllers/surveyor_gui/responses_controller.rb +39 -0
- data/app/controllers/surveyor_gui/survey_controller.rb +16 -0
- data/app/facades/report_formatter.rb +44 -0
- data/app/facades/report_preview_wrapper.rb +11 -0
- data/app/facades/report_response_generator.rb +147 -0
- data/app/helpers/application_helper.rb +2 -0
- data/app/helpers/dependency_helper.rb +5 -0
- data/app/helpers/question_helper.rb +22 -0
- data/app/helpers/surveyform_helper.rb +179 -0
- data/app/helpers/surveyor_gui/report_helper.rb +19 -0
- data/app/helpers/surveyor_helper.rb +4 -0
- data/app/inputs/currency_input.rb +5 -0
- data/app/inputs/date_picker_input.rb +7 -0
- data/app/inputs/datetime_picker_input.rb +5 -0
- data/app/inputs/percent_input.rb +5 -0
- data/app/inputs/time_picker_input.rb +5 -0
- data/app/mailers/.gitkeep +0 -0
- data/app/models/.gitkeep +0 -0
- data/app/models/answer.rb +4 -0
- data/app/models/column.rb +3 -0
- data/app/models/dependency.rb +4 -0
- data/app/models/dependency_condition.rb +4 -0
- data/app/models/permitted_params_decorator.rb +80 -0
- data/app/models/question.rb +4 -0
- data/app/models/question_group.rb +4 -0
- data/app/models/question_type.rb +7 -0
- data/app/models/response.rb +4 -0
- data/app/models/response_set.rb +4 -0
- data/app/models/row.rb +3 -0
- data/app/models/survey.rb +4 -0
- data/app/models/survey_section.rb +4 -0
- data/app/models/surveyform.rb +103 -0
- data/app/uploaders/blob_uploader.rb +48 -0
- data/app/views/dependencys/_column.html.erb +1 -0
- data/app/views/dependencys/_dependency.html.erb +22 -0
- data/app/views/dependencys/_dependency_condition_fields.html.erb +48 -0
- data/app/views/dependencys/_form.html.erb +20 -0
- data/app/views/dependencys/blank.html.erb +0 -0
- data/app/views/dependencys/edit.html.erb +1 -0
- data/app/views/dependencys/new.html.erb +1 -0
- data/app/views/layouts/application.html.erb +14 -0
- data/app/views/layouts/surveyor_gui_blank.html.erb +12 -0
- data/app/views/layouts/surveyor_gui_default.html.erb +16 -0
- data/app/views/layouts/surveyor_modified.html.erb +14 -0
- data/app/views/partials/_answer.html.haml +33 -0
- data/app/views/partials/_question.html.haml +33 -0
- data/app/views/partials/_question_group.html.haml +73 -0
- data/app/views/partials/_section.html.haml +13 -0
- data/app/views/question_groups/_form.html.erb +56 -0
- data/app/views/question_groups/_group_inline_field.html.erb +21 -0
- data/app/views/question_groups/_group_inline_fields.html.erb +25 -0
- data/app/views/question_groups/blank.html.erb +0 -0
- data/app/views/question_groups/edit.html.erb +1 -0
- data/app/views/question_groups/new.html.erb +1 -0
- data/app/views/questions/_answer_fields.html.erb +23 -0
- data/app/views/questions/_answer_options.html.erb +28 -0
- data/app/views/questions/_form.html.erb +65 -0
- data/app/views/questions/_grid_dropdown_columns.html.erb +10 -0
- data/app/views/questions/_grid_dropdown_fields.html.erb +42 -0
- data/app/views/questions/_grid_fields.html.erb +9 -0
- data/app/views/questions/_no_picks.html.erb +29 -0
- data/app/views/questions/_pick.html +21 -0
- data/app/views/questions/_picks.html.erb +12 -0
- data/app/views/questions/blank.html.erb +0 -0
- data/app/views/questions/edit.html.erb +1 -0
- data/app/views/questions/new.html.erb +1 -0
- data/app/views/survey_sections/_form.html.erb +13 -0
- data/app/views/survey_sections/blank.html.erb +0 -0
- data/app/views/survey_sections/edit.html.erb +1 -0
- data/app/views/survey_sections/new.html.erb +1 -0
- data/app/views/surveyforms/_form.html.erb +50 -0
- data/app/views/surveyforms/_question_field.html.erb +148 -0
- data/app/views/surveyforms/_question_group.html.erb +116 -0
- data/app/views/surveyforms/_question_group_fields.html.erb +3 -0
- data/app/views/surveyforms/_question_name_and_number.html.erb +6 -0
- data/app/views/surveyforms/_question_section.html.erb +15 -0
- data/app/views/surveyforms/_question_wrapper.html.erb +109 -0
- data/app/views/surveyforms/_survey_section_fields.html.erb +138 -0
- data/app/views/surveyforms/clone_survey.html.erb +13 -0
- data/app/views/surveyforms/edit.html.erb +5 -0
- data/app/views/surveyforms/index.html.erb +40 -0
- data/app/views/surveyforms/new.html.erb +1 -0
- data/app/views/surveyforms/show.html.erb +5 -0
- data/app/views/surveyor_gui/reports/_graphs.html.haml +21 -0
- data/app/views/surveyor_gui/reports/_grid.html.haml +42 -0
- data/app/views/surveyor_gui/reports/_grid_dropdown.html.haml +56 -0
- data/app/views/surveyor_gui/reports/_repeater.html.haml +28 -0
- data/app/views/surveyor_gui/reports/_show_report.html.haml +33 -0
- data/app/views/surveyor_gui/reports/_single_question.html.haml +70 -0
- data/app/views/surveyor_gui/reports/show.html.erb +14 -0
- data/app/views/surveyor_gui/responses/_grid.html.haml +20 -0
- data/app/views/surveyor_gui/responses/_grid_dropdown.html.haml +20 -0
- data/app/views/surveyor_gui/responses/_repeater.html.haml +22 -0
- data/app/views/surveyor_gui/responses/_survey_results.html.haml +40 -0
- data/app/views/surveyor_gui/responses/index.html.haml +24 -0
- data/app/views/surveyor_gui/responses/show.html.haml +42 -0
- data/app/views/surveyor_gui/shared/_grid_comments.html.haml +10 -0
- data/app/views/surveyor_gui/shared/_new_line.html.haml +2 -0
- data/app/views/surveyor_gui/shared/_pick_comments.html.haml +15 -0
- data/app/views/surveyor_gui/shared/_question_number.html.haml +9 -0
- data/app/views/surveyor_gui/shared/_report_data.html.haml +24 -0
- data/app/views/surveyor_gui/shared/_stars_report_data.html.haml +14 -0
- data/config.ru +4 -0
- data/config/environment.rb +0 -0
- data/config/routes.rb +71 -0
- data/db/migrate/20140307204049_add_template_to_surveys.rb +5 -0
- data/db/migrate/20140307235607_add_test_data_to_response_sets.rb +5 -0
- data/db/migrate/20140308171947_add_original_choice_to_answers.rb +5 -0
- data/db/migrate/20140308172118_add_blob_to_responses.rb +5 -0
- data/db/migrate/20140308172417_add_modifiable_to_survey_section.rb +5 -0
- data/db/migrate/20140308174532_add_modifiable_to_question.rb +5 -0
- data/db/migrate/20140308175305_add_dynamically_generate_to_questions.rb +5 -0
- data/db/migrate/20140311032923_add_dummy_blob_to_questions.rb +5 -0
- data/db/migrate/20140311160609_add_dynamic_source_to_questions.rb +5 -0
- data/db/migrate/20140311161714_add_report_code_to_questions.rb +5 -0
- data/db/migrate/20140530181134_add_is_comment_to_questions.rb +5 -0
- data/db/migrate/20140531012006_add_is_comment_to_answers.rb +5 -0
- data/db/migrate/20140531225529_create_rows.rb +9 -0
- data/db/migrate/20140601011151_create_columns.rb +11 -0
- data/db/migrate/20140602030330_add_column_id_to_answers.rb +5 -0
- data/db/migrate/20140603155606_add_column_id_to_responses.rb +5 -0
- data/db/migrate/20140606023527_add_column_id_to_dependency_conditions.rb +5 -0
- data/db/migrate/20140815165307_add_user_id_to_survey.rb +5 -0
- data/lib/assets/.gitkeep +0 -0
- data/lib/assets/images/addicon.png +0 -0
- data/lib/assets/images/datepicker.gif +0 -0
- data/lib/assets/images/delete.gif +0 -0
- data/lib/assets/images/delete.png +0 -0
- data/lib/assets/images/images/border.png +0 -0
- data/lib/assets/images/images/controls.png +0 -0
- data/lib/assets/images/images/loading.gif +0 -0
- data/lib/assets/images/images/loading_background.png +0 -0
- data/lib/assets/images/images/overlay.png +0 -0
- data/lib/assets/images/rails.png +0 -0
- data/lib/assets/images/star.gif +0 -0
- data/lib/assets/javascripts/.gitkeep +0 -0
- data/lib/assets/javascripts/surveyor_gui/jquery.MetaData.js +121 -0
- data/lib/assets/javascripts/surveyor_gui/jquery.blockUI.js +619 -0
- data/lib/assets/javascripts/surveyor_gui/jquery.rating.js +377 -0
- data/lib/assets/javascripts/surveyor_gui/jquery.validate.js +1188 -0
- data/lib/assets/javascripts/surveyor_gui/surveyor_add_ons.js +10 -0
- data/lib/assets/javascripts/surveyor_gui/surveyor_gui.js +1417 -0
- data/lib/assets/stylesheets/.gitkeep +0 -0
- data/lib/assets/stylesheets/surveyor_gui/jquery.rating.css +12 -0
- data/lib/assets/stylesheets/surveyor_gui/surveyor_add_ons.css +3 -0
- data/lib/assets/stylesheets/surveyor_gui/surveyor_gui.sass +650 -0
- data/lib/enumerable_extenders.rb +31 -0
- data/lib/generators/surveyor_gui/install_generator.rb +57 -0
- data/lib/generators/surveyor_gui/templates/app/assets/javascripts/surveyor_add_ons.js +2 -0
- data/lib/generators/surveyor_gui/templates/app/assets/javascripts/surveyor_gui_all.js +24 -0
- data/lib/generators/surveyor_gui/templates/app/assets/stylesheets/surveyor_add_ons.css.sass +1 -0
- data/lib/generators/surveyor_gui/templates/app/assets/stylesheets/surveyor_gui_all.css.sass +8 -0
- data/lib/generators/surveyor_gui/templates/app/helpers/surveyor_helper.rb +4 -0
- data/lib/generators/surveyor_gui/templates/app/models/response_set_user.rb +13 -0
- data/lib/generators/surveyor_gui/templates/app/views/layouts/surveyor_gui_default.html.erb +16 -0
- data/lib/generators/surveyor_gui/templates/config/initializers/simple_form.rb +140 -0
- data/lib/generators/surveyor_gui/templates/config/locales/en.yml +5 -0
- data/lib/surveyor_gui.rb +17 -0
- data/lib/surveyor_gui/engine.rb +30 -0
- data/lib/surveyor_gui/helpers/surveyor_helper_methods.rb +19 -0
- data/lib/surveyor_gui/models/answer_methods.rb +24 -0
- data/lib/surveyor_gui/models/column_methods.rb +43 -0
- data/lib/surveyor_gui/models/dependency_condition_methods.rb +53 -0
- data/lib/surveyor_gui/models/dependency_methods.rb +83 -0
- data/lib/surveyor_gui/models/question_and_group_shared_methods.rb +11 -0
- data/lib/surveyor_gui/models/question_group_methods.rb +55 -0
- data/lib/surveyor_gui/models/question_methods.rb +435 -0
- data/lib/surveyor_gui/models/question_type_methods.rb +493 -0
- data/lib/surveyor_gui/models/response_methods.rb +67 -0
- data/lib/surveyor_gui/models/response_set_methods.rb +54 -0
- data/lib/surveyor_gui/models/row_methods.rb +11 -0
- data/lib/surveyor_gui/models/survey_methods.rb +32 -0
- data/lib/surveyor_gui/models/survey_section_methods.rb +32 -0
- data/lib/surveyor_gui/surveyforms_controller_methods.rb +258 -0
- data/lib/surveyor_gui/version.rb +3 -0
- data/lib/tasks/.gitkeep +0 -0
- data/lib/tasks/surveyor_gui_tasks.rake +4 -0
- data/lib/templates/erb/scaffold/_form.html.erb +13 -0
- data/spec/controllers/surveyforms_controller_spec.rb +361 -0
- data/spec/controllers/surveyor_controller_spec.rb +303 -0
- data/spec/factories.rb +181 -0
- data/spec/features/create_survey_spec.rb +418 -0
- data/spec/features/dependencies_spec.rb +61 -0
- data/spec/features/rearrange_survey_spec.rb +118 -0
- data/spec/features/ui_spec.rb +469 -0
- data/spec/fixtures/REDCapDemoDatabase_DataDictionary.csv +127 -0
- data/spec/fixtures/chinese_survey.rb +14 -0
- data/spec/fixtures/everything.rb +215 -0
- data/spec/fixtures/favorites-ish.rb +22 -0
- data/spec/fixtures/favorites.rb +22 -0
- data/spec/fixtures/feelings.rb +38 -0
- data/spec/fixtures/lifestyle.rb +55 -0
- data/spec/fixtures/numbers.rb +21 -0
- data/spec/fixtures/redcap_new_headers.csv +1 -0
- data/spec/fixtures/redcap_siblings.csv +1 -0
- data/spec/fixtures/redcap_whitespace.csv +1 -0
- data/spec/helpers/formtastic_custom_input_spec.rb +15 -0
- data/spec/helpers/surveyor_helper_spec.rb +116 -0
- data/spec/lib/common_spec.rb +37 -0
- data/spec/lib/parser_spec.rb +393 -0
- data/spec/lib/rake_kitchen_sink.rb +42 -0
- data/spec/lib/redcap_parser_spec.rb +129 -0
- data/spec/lib/unparser_spec.rb +126 -0
- data/spec/models/answer_spec.rb +144 -0
- data/spec/models/dependency_condition_spec.rb +428 -0
- data/spec/models/dependency_spec.rb +90 -0
- data/spec/models/question_group_spec.rb +66 -0
- data/spec/models/question_spec.rb +176 -0
- data/spec/models/response_set_spec.rb +452 -0
- data/spec/models/response_spec.rb +208 -0
- data/spec/models/survey_section_spec.rb +58 -0
- data/spec/models/survey_spec.rb +155 -0
- data/spec/models/surveyor_gui/question_spec.rb +60 -0
- data/spec/models/surveyor_gui/question_type_spec.rb +268 -0
- data/spec/models/validation_condition_spec.rb +98 -0
- data/spec/models/validation_spec.rb +64 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +119 -0
- data/spec/support/scenario_outline_helper.rb +39 -0
- data/spec/support/shared.rb +10 -0
- data/spec/support/surveyforms_creation_helpers.rb +312 -0
- data/spec/support/surveyforms_rearrangement_helpers.rb +170 -0
- data/spec/support/surveyor_api_helpers.rb +15 -0
- data/spec/support/surveyor_ui_helpers.rb +108 -0
- data/spec/support/wait_for_ajax.rb +11 -0
- data/spec/views/questions/edit.html.erb_spec.rb +73 -0
- data/spec/views/surveyforms/edit.html.erb_spec.rb +126 -0
- data/surveyor_gui.gemspec +52 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.gitkeep +0 -0
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/lib/assets/.gitkeep +0 -0
- data/test/dummy/log/.gitkeep +0 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/surveyor-gui_test.rb +7 -0
- data/test/test_helper.rb +15 -0
- data/vendor/assets/stylesheets/.gitkeep +0 -0
- data/vendor/assets/stylesheets/custom.sass +5 -0
- data/vendor/plugins/.gitkeep +0 -0
- metadata +664 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 01ff64c99fbe1b160d2a285be9d7542b78ae1475
|
4
|
+
data.tar.gz: 5446a1b7ec3ed1a52075fe7581f303930c61b518
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7483d8876d1d10aa8b685ae2f554443d5c3912b7af468a086f260adf0fc6de5d4579c1ed9799140b04bfd8a9c7e5d96223a575e2353640d2e21562d9c5142db0
|
7
|
+
data.tar.gz: 8d7b4471e2a80f408842d765bc1421c233a0bc6ea6180f4fa66dac81e2bd5b21fc0f0ce839046e1fd10e11736f0c0c513ae94ff1eda8b5a4b13ec715eaf198bf
|
data/.gitignore
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
*~
|
2
|
+
*.rbc
|
3
|
+
*.sassc
|
4
|
+
.sass-cache
|
5
|
+
capybara-*.html
|
6
|
+
.rspec
|
7
|
+
.rvmrc
|
8
|
+
/vendor/bundle
|
9
|
+
/log/*
|
10
|
+
log/*
|
11
|
+
/tmp/*
|
12
|
+
/public/system/*
|
13
|
+
/coverage/
|
14
|
+
/spec/tmp/*
|
15
|
+
**.orig
|
16
|
+
**.swp
|
17
|
+
rerun.txt
|
18
|
+
pickle-email-*.html
|
19
|
+
.project
|
20
|
+
config/initializers/secret_token.rb
|
21
|
+
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
22
|
+
#
|
23
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
24
|
+
# or operating system, you probably want to add a global ignore instead:
|
25
|
+
# git config --global core.excludesfile ~/.gitignore_global
|
26
|
+
|
27
|
+
# Ignore bundler config
|
28
|
+
/.bundle
|
29
|
+
|
30
|
+
# Ignore the default SQLite database.
|
31
|
+
/db/*.sqlite3
|
32
|
+
|
33
|
+
# Ignore all logfiles and tempfiles.
|
34
|
+
/log/*.log
|
35
|
+
/tmp
|
36
|
+
|
37
|
+
# Ignore testbed
|
38
|
+
testbed
|
39
|
+
|
40
|
+
# Ignore RVM directives
|
41
|
+
.ruby-version
|
42
|
+
.ruby-gemset
|
43
|
+
|
44
|
+
Gemfile.lock
|
data/.travis.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.0.0
|
4
|
+
- 2.1.1
|
5
|
+
env:
|
6
|
+
- "RAILS_VERSION=4.0.8"
|
7
|
+
- "RAILS_VERSION=4.1.4"
|
8
|
+
script:
|
9
|
+
- bundle exec rake gui_testbed
|
10
|
+
- bundle exec rspec
|
11
|
+
notifications:
|
12
|
+
email:
|
13
|
+
recipients:
|
14
|
+
- kjayma@gmail.com
|
15
|
+
on_success: change # [always|never|change] # default: change
|
16
|
+
on_failure: always # [always|never|change] # default: always
|
17
|
+
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
surveyor_gui
|
2
|
+
============
|
3
|
+
|
4
|
+
Surveyor_gui complements the surveyor gem.
|
5
|
+
|
6
|
+
The surveyor gem is used to create surveys by parsing a file written in the Surveyor DSL. It does not include a gui for creating surveys, although it does provide a gui for taking surveys.
|
7
|
+
|
8
|
+
The lack of a gui front-end limits the utility of surveyor for certain applications.
|
9
|
+
|
10
|
+
Surveyor_gui meets this need by providing a gui to create surveys from scratch. Surveyor_gui bypasses the need to create a Surveyor DSL file, and directly updates the Surveyor tables to build a survey.
|
11
|
+
|
12
|
+
Surveyor is feature-rich and can create very complex surveys. Surveyor-gui supports most of the features in Surveyor.
|
13
|
+
|
14
|
+
This gem will also provide a reporting capability for Surveyor.
|
15
|
+
|
16
|
+
## Requirements
|
17
|
+
|
18
|
+
SurveyorGui works with:
|
19
|
+
|
20
|
+
* Ruby 1.9.3
|
21
|
+
* Rails 4, 4.1
|
22
|
+
|
23
|
+
|
24
|
+
Some key dependencies are:
|
25
|
+
|
26
|
+
* Surveyor
|
27
|
+
* HAML
|
28
|
+
* Sass
|
29
|
+
* Formtastic
|
30
|
+
|
31
|
+
A more exhaustive list can be found in the gemspecs for Surveyor [surveyor] and Surveyor_gui [surveyor-gui][].
|
32
|
+
|
33
|
+
[surveyor]: https://github.com/NUBIC/surveyor/blob/master/surveyor.gemspec
|
34
|
+
[surveyor-gui]: https://github.com/kjayma/surveyor_gui/blob/master/surveyor_gui.gemspec
|
35
|
+
[policy]: http://weblog.rubyonrails.org/2013/2/24/maintenance-policy-for-ruby-on-rails/
|
36
|
+
|
37
|
+
## Install
|
38
|
+
|
39
|
+
Add surveyor and surveyor-gui to your Gemfile:
|
40
|
+
|
41
|
+
gem 'surveyor', github: 'NUBIC/surveyor'
|
42
|
+
gem 'surveyor_gui'
|
43
|
+
|
44
|
+
You will also need a javascript runtime, like node.js or therubyracer. If you
|
45
|
+
have not yet installed one, add
|
46
|
+
|
47
|
+
gem "therubyracer"
|
48
|
+
|
49
|
+
to your Gemfile.
|
50
|
+
|
51
|
+
Bundle, install, and migrate:
|
52
|
+
|
53
|
+
bundle install
|
54
|
+
rails g surveyor_gui:install
|
55
|
+
|
56
|
+
Note that the installer will run db:migrate (so any un-applied migrations you have in your project will be pulled in).
|
57
|
+
The survey editor can be found at '/surveyforms'. Users can take surveys at the '/surveys' url.
|
58
|
+
|
59
|
+
## Limitations
|
60
|
+
|
61
|
+
This gem provides support for a subset of the Surveyor functionality. It supports all of the basic question types, and
|
62
|
+
most of the complicated question types, but does not currently support the following:
|
63
|
+
|
64
|
+
- Questions with multiple entries (e.g., the "Get me started on an improv sketch" question in the kitchen_sink_survey.rb that comes
|
65
|
+
with the Surveyor gem.
|
66
|
+
- Input masks
|
67
|
+
- Quizzes
|
68
|
+
|
69
|
+
It adds some new question types:
|
70
|
+
|
71
|
+
- Star rating (1-5 stars)
|
72
|
+
- File upload
|
73
|
+
- Grid dropdown (a grid of dropdowns with up to ten columns.)
|
74
|
+
|
75
|
+
Dependencies are partially supported. The following are not currently supported:
|
76
|
+
|
77
|
+
- counts (count the number of answers checked or entered)
|
78
|
+
- Regexp validations
|
79
|
+
|
80
|
+
You can open the kitchen_sink survey that comes with Surveyor, but a few of the questions will not behave as expected
|
81
|
+
because of the discrepancies noted above.
|
82
|
+
|
83
|
+
## Locking
|
84
|
+
|
85
|
+
This gem enforces locking on surveys. A survey may be modified up until a user submits a response. At that point, the survey
|
86
|
+
can no longer be edited for structural changes (i.e., /surveyform/edit will not permit any changes). This protects the
|
87
|
+
data integrity of the survey response data.
|
88
|
+
|
89
|
+
## Templates
|
90
|
+
|
91
|
+
Surveys may be saved as templates. This allows them to be cloned when creating a new survey (cloning is a pending feature). It is
|
92
|
+
possible to mark certain parts of a survey as unmodifiable so that they will always be present when a survey is cloned.
|
93
|
+
|
94
|
+
A template library feature is pending.
|
95
|
+
|
96
|
+
## Test environment
|
97
|
+
|
98
|
+
If you want to try out surveyor-gui before incorporating it into an application, or contribute, clone the repository.
|
99
|
+
Then run
|
100
|
+
|
101
|
+
bundle install
|
102
|
+
bundle exec rake gui_testbed
|
103
|
+
cd testbed
|
104
|
+
|
105
|
+
Start the rails server and go to /surveyforms
|
106
|
+
|
107
|
+
Before contributing, please run the tests:
|
108
|
+
bundle exec rspec spec
|
109
|
+
|
110
|
+
## Taking surveys
|
111
|
+
|
112
|
+
Go to /surveys (or click the link at the bottom of the surveyforms home page) to see the surveys and take one.
|
113
|
+
|
114
|
+
## Reports
|
115
|
+
|
116
|
+
Surveyor_gui now provides reports!
|
117
|
+
|
118
|
+
You can see a report of all survey responses, or view an individual response.
|
119
|
+
|
120
|
+
Highcharts.js is used for graphics, and must be licensed for commercial use. Future development will replace Highcharts with Rickshawgraphs.
|
121
|
+
|
122
|
+
To see reports, try using the "Preview Reports" button on the survey editor, or take the survey and try
|
123
|
+
"localhost:3000/surveyor_gui/reports/:id/show" where :id is the survey id. Preview reports will create some dummy
|
124
|
+
responses using randomized answers.
|
125
|
+
|
126
|
+
You can also view an individual response at "localhost:3000/surveyor_gui/results/:id/show".
|
127
|
+
|
128
|
+
## Devise etc.
|
129
|
+
|
130
|
+
Surveyor_Gui will work with Devise or like gems.
|
131
|
+
|
132
|
+
Surveyor_gui adds a user_id attribute to the Survey model. It will try to set user_id to current_user when a new survey
|
133
|
+
is defined. The gem does not provide any access control over survey creation and update, but you can add that to your
|
134
|
+
application using the user_id attribute.
|
135
|
+
|
136
|
+
In addition, the underlying Surveyor gem provides a user_id attribute in the ResponseSet model. When responses are created, it will
|
137
|
+
try to set the user_id to current_user.
|
138
|
+
|
139
|
+
Surveyor_gui reports assume there will be a unique user for eash Survey response, and reports on results by user.
|
140
|
+
If the response set has a user id, (which will be the case if you've setup Devise in the typical way) it will identify the response by user_id. If no user_id is available, it will
|
141
|
+
default to the response_set.id.
|
142
|
+
|
143
|
+
You may want to identify users by something other than id on reports. This can be done easily.
|
144
|
+
|
145
|
+
Surveyor_gui creates a response_set_user.rb file in your app/models directory. Edit it to define the identifier you would like to use for users in reports. For instance, if your user model is User, and you would like to see the user's email address on reports, edit the file as follows...
|
146
|
+
|
147
|
+
In the initialize method, add the following line:
|
148
|
+
|
149
|
+
@user = User.find(user_id)
|
150
|
+
|
151
|
+
In the report_user_name method, add the following line:
|
152
|
+
|
153
|
+
@user ? @user.email : nil
|
154
|
+
|
155
|
+
If you wanted the users full name, you could add something like this:
|
156
|
+
|
157
|
+
@user ? @user.last_name + ', ' + @user.first_name : nil
|
158
|
+
|
159
|
+
Note that SurveyorGui controllers expect to use surveyor_gui's own layout view, surveyor_gui_default.rb. A copy will be placed in your application's app/views/layouts directory. You may need edit it for various reasons, such as adding a Devise login/logout link.
|
data/Rakefile
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
$LOAD_PATH << File.expand_path('../lib', __FILE__)
|
2
|
+
|
3
|
+
|
4
|
+
require 'bundler/gem_tasks'
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
|
7
|
+
###### RSPEC
|
8
|
+
|
9
|
+
RSpec::Core::RakeTask.new(:spec)
|
10
|
+
|
11
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
12
|
+
spec.rcov = true
|
13
|
+
end
|
14
|
+
|
15
|
+
task :default => :spec
|
16
|
+
|
17
|
+
|
18
|
+
###### TESTBED
|
19
|
+
|
20
|
+
desc 'Set up the rails app that the specs and features use'
|
21
|
+
task :gui_testbed => 'gui_testbed:rebuild'
|
22
|
+
|
23
|
+
namespace :gui_testbed do
|
24
|
+
desc 'Generate a minimal surveyor_gui/surveyor rails app'
|
25
|
+
task :generate do
|
26
|
+
sh "bundle exec rails new testbed --skip-bundle" # don't run bundle install until the Gemfile modifications
|
27
|
+
|
28
|
+
chdir('testbed') do
|
29
|
+
gem_file_contents = File.read('Gemfile')
|
30
|
+
gem_file_contents.sub!(/^(gem 'rails'.*)$/, %Q{ \\1\nplugin_root = File.expand_path('../..', __FILE__)\ngem 'surveyor_gui', :path => plugin_root\ngem 'therubyracer'\ngem 'surveyor', github: 'NUBIC/surveyor'})
|
31
|
+
|
32
|
+
File.open('Gemfile', 'w'){|f| f.write(gem_file_contents) }
|
33
|
+
|
34
|
+
# not sure why turbolinks gives test problems, anyway better to avoid it?
|
35
|
+
js_file_contents = File.read('app/assets/javascripts/application.js')
|
36
|
+
js_file_contents.sub!('//= require turbolinks', '')
|
37
|
+
File.open('app/assets/javascripts/application.js', 'w'){|f| f.write(js_file_contents) }
|
38
|
+
|
39
|
+
Bundler.with_clean_env do
|
40
|
+
sh 'bundle install' # run bundle install after Gemfile modifications
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
desc 'Remove the testbed entirely'
|
46
|
+
task :remove do
|
47
|
+
rm_rf 'testbed'
|
48
|
+
end
|
49
|
+
|
50
|
+
desc 'Prepare the databases for the testbed'
|
51
|
+
task :migrate do
|
52
|
+
chdir('testbed') do
|
53
|
+
Bundler.with_clean_env do
|
54
|
+
sh 'bundle exec rails generate simple_form:install'
|
55
|
+
sh 'bundle exec rake highcharts:update'
|
56
|
+
sh 'bundle exec rails generate surveyor:install'
|
57
|
+
sh 'bundle exec rake db:migrate db:test:prepare'
|
58
|
+
sh 'bundle exec rails generate surveyor_gui:install'
|
59
|
+
sh 'bundle exec rake db:migrate db:test:prepare'
|
60
|
+
sh 'bundle exec rake surveyor FILE=surveys/kitchen_sink_survey.rb'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
task :rebuild => [:remove, :generate, :migrate]
|
66
|
+
end
|
@@ -0,0 +1,286 @@
|
|
1
|
+
class DependencysController < ApplicationController
|
2
|
+
layout 'surveyor_gui_blank'
|
3
|
+
|
4
|
+
def new
|
5
|
+
prep_variables
|
6
|
+
@title = "Add Logic for "+@this_question
|
7
|
+
if @question.part_of_group?
|
8
|
+
@question.question_group.build_dependency(:rule=>'A')
|
9
|
+
else
|
10
|
+
@question.build_dependency(:rule=>'A')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def edit
|
15
|
+
prep_variables
|
16
|
+
@title = "Edit Logic for Question "+@this_question
|
17
|
+
end
|
18
|
+
|
19
|
+
def create
|
20
|
+
@question = Question.new(question_params)
|
21
|
+
if @question.save
|
22
|
+
redirect_to :back
|
23
|
+
else
|
24
|
+
render :action => 'new', :layout => 'surveyor_gui_blank'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def update
|
29
|
+
@title = "Update Question"
|
30
|
+
@question = Question.includes(:answers).find(params[:id])
|
31
|
+
if @question.part_of_group?
|
32
|
+
update_object = @question.question_group
|
33
|
+
update_params = question_group_params
|
34
|
+
else
|
35
|
+
update_object = @question
|
36
|
+
update_params = question_params
|
37
|
+
end
|
38
|
+
if update_object.update_attributes(update_params)
|
39
|
+
update_object.dependency.destroy if update_object.dependency.dependency_conditions.blank?
|
40
|
+
render :blank, :layout => 'surveyor_gui_blank'
|
41
|
+
else
|
42
|
+
prep_variables
|
43
|
+
render :action => 'edit', :layout => 'surveyor_gui_blank'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def destroy
|
48
|
+
question = Question.find(params[:id])
|
49
|
+
if question.part_of_group?
|
50
|
+
question.question_group.dependency.destroy
|
51
|
+
else
|
52
|
+
question.dependency.destroy
|
53
|
+
end
|
54
|
+
render :nothing=>true
|
55
|
+
end
|
56
|
+
|
57
|
+
def render_dependency_conditions_partial
|
58
|
+
prep_variables
|
59
|
+
@question_or_group = @question.part_of_group? ? @question.question_group : @question
|
60
|
+
@dependency = Dependency.find(params[:dependency_id]) if !params[:dependency_id].blank?
|
61
|
+
if @dependency.nil?
|
62
|
+
@question_or_group.build_dependency(:rule=>'A').dependency_conditions.build()
|
63
|
+
end
|
64
|
+
if @question_or_group.dependency.dependency_conditions.empty?
|
65
|
+
@question_or_group.dependency.dependency_conditions.build()
|
66
|
+
else
|
67
|
+
if params[:add_row]
|
68
|
+
@question_or_group = eval(@question_or_group.class.name).new
|
69
|
+
@question_or_group.build_dependency.dependency_conditions.build()
|
70
|
+
end
|
71
|
+
end
|
72
|
+
render :partial => 'dependency_condition_fields'
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_answers
|
76
|
+
options=""
|
77
|
+
question_id = params[:question_id]
|
78
|
+
question = Question.find(question_id)
|
79
|
+
column_id = params[:column_id].blank? ? _default_column_id(question) : params[:column_id]
|
80
|
+
dependency_condition_id = params[:dependency_condition_id]
|
81
|
+
dependency_condition = dependency_condition_id.blank? ? nil : DependencyCondition.find(dependency_condition_id)
|
82
|
+
if question && question.answers
|
83
|
+
question.answers.where('column_id = ? OR column_id IS NULL',column_id.to_i).each_with_index do |a, index|
|
84
|
+
options += '<option ' + _get_selected_answer(index, dependency_condition, a, column_id) +
|
85
|
+
'value="' + a.id.to_s + '"' +
|
86
|
+
'>'+a.text.to_s+"</option>"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
render :inline=>options
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_columns
|
93
|
+
options=""
|
94
|
+
question_id = params[:question_id]
|
95
|
+
dependency_condition_id = params[:dependency_condition_id]
|
96
|
+
dependency_condition = dependency_condition_id.blank? ? nil : DependencyCondition.find(dependency_condition_id)
|
97
|
+
question = Question.find(question_id)
|
98
|
+
if question && question.question_group
|
99
|
+
question.question_group.columns.each_with_index do |c, index|
|
100
|
+
options += '<option ' +
|
101
|
+
_get_selected_column(index, dependency_condition, c) +
|
102
|
+
'value="' + c.id.to_s + '"' +
|
103
|
+
'>'+c.text.to_s+"</option>"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
render :inline=>options
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_question_type
|
110
|
+
question_id = params[:question_id]
|
111
|
+
question = Question.find(question_id)
|
112
|
+
response=question.pick
|
113
|
+
response += ','+question.question_type_id.to_s
|
114
|
+
response += ','+question_id
|
115
|
+
render :inline=>response
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def prep_variables
|
121
|
+
@question = Question.includes(:dependency).find(params[:id]) unless @question
|
122
|
+
controlling_questions = get_controlling_question_collection(@question)
|
123
|
+
@controlling_questions = controlling_questions.collection
|
124
|
+
@this_question = @question.part_of_group? ? @question.question_group.text : @question.question_description
|
125
|
+
@operators = get_operators
|
126
|
+
end
|
127
|
+
|
128
|
+
def get_controlling_question_collection(dependent_question)
|
129
|
+
all_questions_in_survey = _get_all_questions_in_survey(dependent_question)
|
130
|
+
_get_question_collection(all_questions_in_survey, dependent_question)
|
131
|
+
end
|
132
|
+
|
133
|
+
def _get_all_questions_in_survey(question)
|
134
|
+
PossibleControllingQuestion.unscoped
|
135
|
+
.joins(:survey_section)
|
136
|
+
.where('survey_id = ?', question.survey_section.survey_id)
|
137
|
+
.order('survey_sections.display_order','survey_sections.id','questions.display_order')
|
138
|
+
end
|
139
|
+
|
140
|
+
def _get_question_collection(all_questions, dependent_question)
|
141
|
+
return QuestionCollection.new(dependent_question).add_questions(all_questions)
|
142
|
+
end
|
143
|
+
|
144
|
+
def get_operators
|
145
|
+
return [
|
146
|
+
['equal to (=)','=='],
|
147
|
+
['not equal to','!='],
|
148
|
+
['less than (<)','<'],
|
149
|
+
['less than or equal to (<=)','<='],
|
150
|
+
['greater than or equal to (>=)','>='],
|
151
|
+
['greater than','>']
|
152
|
+
]
|
153
|
+
end
|
154
|
+
|
155
|
+
def question_params
|
156
|
+
::PermittedParams.new(params[:question]).question
|
157
|
+
end
|
158
|
+
|
159
|
+
def question_group_params
|
160
|
+
::PermittedParams.new(params[:question_group]).question_group
|
161
|
+
end
|
162
|
+
|
163
|
+
def _default_column_id(question)
|
164
|
+
if question.part_of_group?
|
165
|
+
columns = question.question_group.columns
|
166
|
+
columns.first ? columns.first.id.to_s : ""
|
167
|
+
else
|
168
|
+
""
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def _get_selected_answer(index, dependency_condition, a, column_id)
|
173
|
+
if _matches_dependency_condition(dependency_condition, a, column_id)
|
174
|
+
'selected="selected" '
|
175
|
+
else
|
176
|
+
''
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def _get_selected_column(index, dependency_condition, column)
|
181
|
+
if _matches_dependency_condition_column(dependency_condition, column)
|
182
|
+
'selected="selected"'
|
183
|
+
else
|
184
|
+
''
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def _matches_dependency_condition (dependency_condition, a, column_id)
|
189
|
+
if dependency_condition.nil?
|
190
|
+
false
|
191
|
+
else
|
192
|
+
(dependency_condition.answer_id == a.id && (column_id.blank? || dependency_condition.column_id == column_id.to_i ))
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def _matches_dependency_condition_column(dependency_condition, column)
|
197
|
+
if dependency_condition.nil?
|
198
|
+
false
|
199
|
+
else
|
200
|
+
dependency_condition.column_id == column.id
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
class QuestionCollection
|
207
|
+
## QuestionCollection provides a 2 dimensional array consisting of a question id
|
208
|
+
## and a question description. The collection may be used in a view's select field.
|
209
|
+
##
|
210
|
+
## Its membership is determined by a base question.
|
211
|
+
## The base question is the one from which other questions in the collection are derived.
|
212
|
+
## E.g., in a dependency, the question that is shown or hidden based on the answers to others
|
213
|
+
## is the base question. It shouldn't show up in the collection.
|
214
|
+
##
|
215
|
+
## Other questions may or may not show up in the collection depending on their eligibility.
|
216
|
+
##
|
217
|
+
## Some questions should have a question number and
|
218
|
+
## some should not. The QuestionCollection numbers questions that should be numbered
|
219
|
+
## and keeps track of the numbering. If a question is numbered, the question number
|
220
|
+
## is included in the description, e.g. "3) What is your name?". Otherwise,
|
221
|
+
## the description is just the question text, e.g. "Don't forget to use your middle initial".
|
222
|
+
##
|
223
|
+
## Incoming questions may be duck typed, but should respond to is_numbered? and is_eligible?
|
224
|
+
## messages.
|
225
|
+
|
226
|
+
attr_accessor :collection, :dependency_question_description
|
227
|
+
|
228
|
+
def initialize(base_question)
|
229
|
+
@collection = []
|
230
|
+
@question_number = 1
|
231
|
+
@base_question = base_question
|
232
|
+
@dependency_question_description = nil
|
233
|
+
end
|
234
|
+
|
235
|
+
def collection
|
236
|
+
@collection
|
237
|
+
end
|
238
|
+
|
239
|
+
def add_questions(questions)
|
240
|
+
questions.each {|q| add_question(q)}
|
241
|
+
return self
|
242
|
+
end
|
243
|
+
|
244
|
+
def add_question(question)
|
245
|
+
_add_to_collection_if_eligible(question)
|
246
|
+
if question.is_numbered?
|
247
|
+
_increment_question_number
|
248
|
+
end
|
249
|
+
return self
|
250
|
+
end
|
251
|
+
|
252
|
+
private
|
253
|
+
|
254
|
+
def _get_description(question)
|
255
|
+
@question_number.to_s + ') ' + (question.part_of_group? ? question.question_group.text + ": " : "") +question.text
|
256
|
+
end
|
257
|
+
|
258
|
+
def _add_to_collection(question)
|
259
|
+
description = _get_description(question)
|
260
|
+
@collection.push([description, question.id])
|
261
|
+
end
|
262
|
+
|
263
|
+
def _add_to_collection_if_eligible(question)
|
264
|
+
_add_to_collection(question) if question.is_eligible? && _this_is_not_the_base_question?(question)
|
265
|
+
end
|
266
|
+
|
267
|
+
def _this_is_not_the_base_question?(question)
|
268
|
+
if question.part_of_group?
|
269
|
+
question.question_group_id != @base_question.question_group_id
|
270
|
+
else
|
271
|
+
question.id != @base_question.id
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def _increment_question_number
|
276
|
+
@question_number += 1
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
## This shouldn't be here but breaks saving nested attributes on question when put
|
281
|
+
## in QuestionMethods. Not sure why, but leave for now and revisit later.
|
282
|
+
class PossibleControllingQuestion < Question
|
283
|
+
def is_eligible?
|
284
|
+
question_type_id!=:label && question_type_id!=:file
|
285
|
+
end
|
286
|
+
end
|