surveyor 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/MIT-LICENSE +20 -0
- data/README.md +104 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/app/controllers/surveyor_controller.rb +117 -0
- data/app/helpers/survey_form_builder.rb +37 -0
- data/app/helpers/surveyor_helper.rb +66 -0
- data/app/models/answer.rb +21 -0
- data/app/models/dependency.rb +46 -0
- data/app/models/dependency_condition.rb +79 -0
- data/app/models/question.rb +54 -0
- data/app/models/question_group.rb +18 -0
- data/app/models/response.rb +47 -0
- data/app/models/response_set.rb +185 -0
- data/app/models/survey.rb +57 -0
- data/app/models/survey_section.rb +15 -0
- data/app/views/layouts/surveyor_default.html.erb +13 -0
- data/app/views/partials/_answer.html.haml +49 -0
- data/app/views/partials/_question.html.haml +73 -0
- data/app/views/partials/_question_group.html.haml +41 -0
- data/app/views/surveyor/edit.html.haml +32 -0
- data/app/views/surveyor/new.html.haml +17 -0
- data/app/views/surveyor/show.html.haml +12 -0
- data/config/routes.rb +10 -0
- data/generators/surveyor/EXTENDING_SURVEYOR +12 -0
- data/generators/surveyor/extend_surveyor_generator.rb +22 -0
- data/generators/surveyor/surveyor_generator.rb +60 -0
- data/generators/surveyor/templates/README +10 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_arrows_leftright.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_arrows_updown.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_close.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_doc.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_folder_closed.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_folder_open.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_minus.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_plus.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_resize_se.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_35x9_colorpicker_indicator.gif.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_7x7_arrow_down.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_7x7_arrow_left.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_7x7_arrow_right.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_7x7_arrow_up.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_arrows_leftright.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_arrows_updown.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_close.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_doc.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_folder_closed.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_folder_open.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_minus.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_plus.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_7x7_arrow_down.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_7x7_arrow_left.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_7x7_arrow_right.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_7x7_arrow_up.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_arrows_leftright.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_arrows_updown.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_close.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_doc.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_folder_closed.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_folder_open.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_minus.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_plus.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_7x7_arrow_down.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_7x7_arrow_left.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_7x7_arrow_right.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_7x7_arrow_up.gif +0 -0
- data/generators/surveyor/templates/assets/images/dadada_40x100_textures_02_glass_75.png +0 -0
- data/generators/surveyor/templates/assets/images/e6e6e6_40x100_textures_02_glass_75.png +0 -0
- data/generators/surveyor/templates/assets/images/ffffff_40x100_textures_01_flat_0.png +0 -0
- data/generators/surveyor/templates/assets/images/ffffff_40x100_textures_02_glass_65.png +0 -0
- data/generators/surveyor/templates/assets/javascripts/accessibleUISlider.jQuery.js +201 -0
- data/generators/surveyor/templates/assets/javascripts/jquery-1.2.6.js +3549 -0
- data/generators/surveyor/templates/assets/javascripts/jquery-ui-personalized-1.5.3.js +7616 -0
- data/generators/surveyor/templates/assets/javascripts/jquery.form.js +637 -0
- data/generators/surveyor/templates/assets/javascripts/surveyor.js +28 -0
- data/generators/surveyor/templates/assets/stylesheets/jquery-ui-slider-additions.css +71 -0
- data/generators/surveyor/templates/assets/stylesheets/reset.css +46 -0
- data/generators/surveyor/templates/assets/stylesheets/sass/surveyor.sass +245 -0
- data/generators/surveyor/templates/assets/stylesheets/surveyor.css +231 -0
- data/generators/surveyor/templates/assets/stylesheets/ui.theme.css +851 -0
- data/generators/surveyor/templates/extensions/survey_extensions.rb +18 -0
- data/generators/surveyor/templates/extensions/surveyor_controller_extensions.rb +28 -0
- data/generators/surveyor/templates/extensions/surveyor_custom.html.erb +13 -0
- data/generators/surveyor/templates/extensions/surveyor_helper_extensions.rb +18 -0
- data/generators/surveyor/templates/initializers/haml.rb +8 -0
- data/generators/surveyor/templates/initializers/surveyor.rb +11 -0
- data/generators/surveyor/templates/migrate/create_answers.rb +45 -0
- data/generators/surveyor/templates/migrate/create_dependencies.rb +21 -0
- data/generators/surveyor/templates/migrate/create_dependency_conditions.rb +29 -0
- data/generators/surveyor/templates/migrate/create_question_groups.rb +18 -0
- data/generators/surveyor/templates/migrate/create_questions.rb +33 -0
- data/generators/surveyor/templates/migrate/create_response_sets.rb +22 -0
- data/generators/surveyor/templates/migrate/create_responses.rb +33 -0
- data/generators/surveyor/templates/migrate/create_survey_sections.rb +25 -0
- data/generators/surveyor/templates/migrate/create_surveys.rb +25 -0
- data/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +201 -0
- data/generators/surveyor/templates/tasks/surveyor.rb +4 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/lib/surveyor.rb +7 -0
- data/lib/surveyor/config.rb +45 -0
- data/lib/tasks/surveyor_tasks.rake +33 -0
- data/lib/tiny_code.rb +58 -0
- data/lib/xml_formatter.rb +12 -0
- data/script/surveyor/answer.rb +84 -0
- data/script/surveyor/columnizer.rb +36 -0
- data/script/surveyor/dependency.rb +43 -0
- data/script/surveyor/dependency_condition.rb +74 -0
- data/script/surveyor/question.rb +76 -0
- data/script/surveyor/question_group.rb +33 -0
- data/script/surveyor/specs/answer_spec.rb +66 -0
- data/script/surveyor/specs/question_dependency_spec.rb +46 -0
- data/script/surveyor/specs/question_group_spec.rb +9 -0
- data/script/surveyor/specs/question_spec.rb +111 -0
- data/script/surveyor/specs/section_spec.rb +58 -0
- data/script/surveyor/survey.rb +108 -0
- data/script/surveyor/survey_parser.rb +64 -0
- data/script/surveyor/survey_section.rb +153 -0
- data/script/surveyor/whr_dsl.tmproj +244 -0
- data/spec/controllers/surveyor_controller_spec.rb +328 -0
- data/spec/factories.rb +107 -0
- data/spec/models/answer_spec.rb +29 -0
- data/spec/models/dependency_condition_spec.rb +338 -0
- data/spec/models/dependency_spec.rb +82 -0
- data/spec/models/question_group_spec.rb +11 -0
- data/spec/models/question_spec.rb +75 -0
- data/spec/models/response_set_spec.rb +153 -0
- data/spec/models/response_spec.rb +94 -0
- data/spec/models/survey_section_spec.rb +34 -0
- data/spec/models/survey_spec.rb +72 -0
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +14 -0
- data/surveyor.gemspec +187 -0
- data/uninstall.rb +1 -0
- metadata +211 -0
data/.gitignore
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008-2009 Brian Chamberlain and Mark Yoon
|
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,104 @@
|
|
1
|
+
# Survey On Rails
|
2
|
+
|
3
|
+
Surveyor is a rails (gem) plugin, that brings surveys to your rails app. Before Rails 2.3, it was implemented as a Rails Engine. Surveys are written in a DSL (Domain Specific Language), with examples available in the "kitchen sink" survey.
|
4
|
+
|
5
|
+
# Installation
|
6
|
+
|
7
|
+
As a plugin:
|
8
|
+
|
9
|
+
sudo gem install haml
|
10
|
+
script/plugin install git://github.com/breakpointer/surveyor.git
|
11
|
+
|
12
|
+
Or as a gem plugin:
|
13
|
+
|
14
|
+
# in environment.rb
|
15
|
+
config.gem "surveyor", :version => '>=0.4.1', :lib => false
|
16
|
+
|
17
|
+
sudo rake gems:install
|
18
|
+
|
19
|
+
Generate assets, run migrations:
|
20
|
+
|
21
|
+
script/generate surveyor
|
22
|
+
rake db:migrate
|
23
|
+
|
24
|
+
Try out the "kitchen sink" survey:
|
25
|
+
|
26
|
+
rake surveyor FILE=surveys/kitchen_sink_survey.rb
|
27
|
+
|
28
|
+
# Configuration
|
29
|
+
|
30
|
+
The surveyor generator creates config/initializers/surveyor.rb. There, you can specify:
|
31
|
+
|
32
|
+
- your own relative root for surveys ('/' is not recommended as any path will be interpreted as a survey name)
|
33
|
+
- your own custom title (string) for the survey list page
|
34
|
+
- your own custom layout file name, in your app/views/layouts folder
|
35
|
+
- your own custom finish url for all surveys. you can give a string (a path), a symbol (the name of a method in ApplicationController)
|
36
|
+
- if you would like surveys to require authorization via the restful_authentication plugin
|
37
|
+
- if you would like to extend the surveyor_controller (see Extending Surveyor below)
|
38
|
+
|
39
|
+
The initializer runs once, when the app starts. The block style is used to keep multiple options DRY (defaults below):
|
40
|
+
|
41
|
+
Surveyor::Config.run do |config|
|
42
|
+
config['default.relative_url_root'] = "surveys/" # should end with '/'
|
43
|
+
config['default.title'] = "You can take these surveys:"
|
44
|
+
config['default.layout'] = "surveyor_default"
|
45
|
+
config['default.finish'] = "/surveys"
|
46
|
+
config['use_restful_authentication'] = false
|
47
|
+
config['extend_controller'] = false
|
48
|
+
end
|
49
|
+
|
50
|
+
You can update surveyor's at any time. Use the block style (above), or the individual style:
|
51
|
+
|
52
|
+
Surveyor::Config['default.title'] = "Cheese is great!"
|
53
|
+
|
54
|
+
To look at the current surveyor configuration:
|
55
|
+
|
56
|
+
Surveyor::Config.to_hash.inspect
|
57
|
+
|
58
|
+
# Extending surveyor
|
59
|
+
|
60
|
+
Surveyor's models, helper, and controller can be extended from custom modules your app/models, app/helpers and app/controllers directories. To generate the sample files and sample layout, run:
|
61
|
+
|
62
|
+
script/generate extend_surveyor
|
63
|
+
|
64
|
+
Any of surveyor's models class_eval, class methods, and instance methods can be modified. Include the following in config/initializers/surveyor.rb:
|
65
|
+
|
66
|
+
require 'models/survey_extensions' # Extended the survey model
|
67
|
+
|
68
|
+
SurveyorHelper class_eval and instance methods can be modified. Include the following in config/initializers/surveyor.rb:
|
69
|
+
|
70
|
+
require 'helpers/surveyor_helper_extensions' # Extend the surveyor helper
|
71
|
+
|
72
|
+
SurveyorController class_eval, class methods, instance methods, and actions can be modified. Action methods should be specified separately in the Actions submodule. Set the following option in config/initializers/surveyor.rb Surveyor::Config block:
|
73
|
+
|
74
|
+
config['extend_controller'] = true
|
75
|
+
|
76
|
+
# Sample layout
|
77
|
+
|
78
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
79
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
80
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
81
|
+
<head>
|
82
|
+
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
|
83
|
+
<title>Survey: <%= controller.action_name %></title>
|
84
|
+
<%= surveyor_includes # calls surveyor_javascripts + surveyor_stylesheets %>
|
85
|
+
</head>
|
86
|
+
<body>
|
87
|
+
<div id="flash"><%= flash[:notice] %></div>
|
88
|
+
<div id="survey_with_menu">
|
89
|
+
<%= yield %>
|
90
|
+
</div>
|
91
|
+
</body>
|
92
|
+
</html>
|
93
|
+
|
94
|
+
The <code>surveyor\_includes</code> helper just calls <code>surveyor\_stylsheets + surveyor\_javascripts</code> which in turn call:
|
95
|
+
|
96
|
+
stylesheet_link_tag 'surveyor/reset', 'surveyor/surveyor', 'surveyor/ui.theme.css','surveyor/jquery-ui-slider-additions'
|
97
|
+
|
98
|
+
javascript_include_tag 'surveyor/jquery-1.2.6.js', 'surveyor/jquery-ui-personalized-1.5.3.js', 'surveyor/accessibleUISlider.jQuery.js','surveyor/jquery.form.js', 'surveyor/surveyor.js'
|
99
|
+
|
100
|
+
# Dependencices
|
101
|
+
|
102
|
+
Surveyor depends on Rails 2.3 and the SASS style sheet language, part of HAML (http://haml.hamptoncatlin.com/download)
|
103
|
+
|
104
|
+
Copyright (c) 2008-2009 Brian Chamberlain and Mark Yoon, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "surveyor"
|
8
|
+
gem.summary = %Q{A rails (gem) plugin to enable surveys in your application}
|
9
|
+
gem.email = "yoon@northwestern.edu"
|
10
|
+
gem.homepage = "http://github.com/breakpointer/surveyor"
|
11
|
+
gem.authors = ["Brian Chamberlain", "Mark Yoon"]
|
12
|
+
gem.add_dependency 'haml'
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'spec/rake/spectask'
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
task :default => :spec
|
35
|
+
|
36
|
+
require 'rake/rdoctask'
|
37
|
+
Rake::RDocTask.new do |rdoc|
|
38
|
+
if File.exist?('VERSION.yml')
|
39
|
+
config = YAML.load(File.read('VERSION.yml'))
|
40
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
41
|
+
else
|
42
|
+
version = ""
|
43
|
+
end
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'rdoc'
|
46
|
+
rdoc.title = "surveyor #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
50
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.6.1
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# The Surveyor controller a user taking a survey. It is semi-RESTful since it does not have a concrete representation model.
|
2
|
+
# The "resource" is a survey attempt/session populating a response set.
|
3
|
+
|
4
|
+
class SurveyorController < ApplicationController
|
5
|
+
|
6
|
+
# Layout
|
7
|
+
layout Surveyor::Config['default.layout'] || 'surveyor_default'
|
8
|
+
|
9
|
+
# Extending surveyor
|
10
|
+
include SurveyorControllerExtensions if Surveyor::Config['extend_controller'] && defined? SurveyorControllerExtensions
|
11
|
+
before_filter :extend_actions
|
12
|
+
|
13
|
+
# RESTful authentication
|
14
|
+
if Surveyor::Config['use_restful_authentication']
|
15
|
+
include AuthenticatedSystem
|
16
|
+
before_filter :login_required
|
17
|
+
end
|
18
|
+
|
19
|
+
# Get the response set or current_user
|
20
|
+
# before_filter :get_response_set, :except => [:new, :create]
|
21
|
+
before_filter :get_current_user, :only => [:new, :create]
|
22
|
+
|
23
|
+
# Actions
|
24
|
+
def new
|
25
|
+
@surveys = Survey.find(:all)
|
26
|
+
end
|
27
|
+
def create
|
28
|
+
if (@survey = Survey.find_by_access_code(params[:survey_code])) && (@response_set = ResponseSet.create(:survey => @survey, :user_id => @current_user))
|
29
|
+
flash[:notice] = "Survey was successfully started."
|
30
|
+
redirect_to(edit_my_survey_path(:survey_code => @survey.access_code, :response_set_code => @response_set.access_code))
|
31
|
+
else
|
32
|
+
flash[:notice] = "Unable to find that survey"
|
33
|
+
redirect_to(available_surveys_path)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
def show
|
37
|
+
end
|
38
|
+
def edit
|
39
|
+
if @response_set = ResponseSet.find_by_access_code(params[:response_set_code], :include => {:responses => [:question, :answer]})
|
40
|
+
@survey = Survey.with_sections.find_by_id(@response_set.survey_id)
|
41
|
+
@sections = @survey.sections
|
42
|
+
@section = params[:section] ? @sections.with_includes.find(section_id_from(params[:section])) || @sections.with_includes.first : @sections.with_includes.first
|
43
|
+
else
|
44
|
+
flash[:notice] = "Unable to find your responses to the survey"
|
45
|
+
redirect_to(available_surveys_path)
|
46
|
+
end
|
47
|
+
|
48
|
+
@dependents = (@response_set.unanswered_dependencies - @section.questions) || []
|
49
|
+
end
|
50
|
+
def update
|
51
|
+
if @response_set = ResponseSet.find_by_access_code(params[:response_set_code], :include => {:responses => :answer})
|
52
|
+
@response_set.current_section_id = params[:current_section_id]
|
53
|
+
else
|
54
|
+
flash[:notice] = "Unable to find your responses to the survey"
|
55
|
+
redirect_to(available_surveys_path)
|
56
|
+
end
|
57
|
+
|
58
|
+
if params[:responses] or params[:response_groups]
|
59
|
+
@response_set.clear_responses
|
60
|
+
saved = @response_set.update_attributes(:response_attributes => (params[:responses] || {}).dup , :response_group_attributes => (params[:response_groups] || {}).dup) #copy (dup) to preserve params because we manipulate params in the response_set methods
|
61
|
+
if (saved && params[:finish])
|
62
|
+
@response_set.complete!
|
63
|
+
saved = @response_set.save!
|
64
|
+
end
|
65
|
+
end
|
66
|
+
respond_to do |format|
|
67
|
+
format.html do
|
68
|
+
if saved && params[:finish]
|
69
|
+
flash[:notice] = "Completed survey"
|
70
|
+
redirect_to surveyor_default_finish
|
71
|
+
else
|
72
|
+
flash[:notice] = "Unable to update survey" if !saved and !saved.nil? # saved.nil? is true if there are no questions on the page (i.e. if it only contains a label)
|
73
|
+
redirect_to :action => "edit", :anchor => anchor_from(params[:section]), :params => {:section => section_id_from(params[:section])}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
# No redirect needed if we're talking to the page via json
|
77
|
+
format.js do
|
78
|
+
render :json => @response_set.all_dependencies.to_json
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# Filters
|
86
|
+
def get_current_user
|
87
|
+
@current_user = self.respond_to?(:current_user) ? self.current_user : nil
|
88
|
+
end
|
89
|
+
|
90
|
+
# Params: the name of some submit buttons store the section we'd like to go to. for repeater questions, an anchor to the repeater group is also stored
|
91
|
+
# e.g. params[:section] = {"1"=>{"question_group_1"=>"<= add row"}}
|
92
|
+
def section_id_from(p)
|
93
|
+
p.respond_to?(:keys) ? p.keys.first : p
|
94
|
+
end
|
95
|
+
def anchor_from(p)
|
96
|
+
p.respond_to?(:keys) && p[p.keys.first].respond_to?(:keys) ? p[p.keys.first].keys.first : nil
|
97
|
+
end
|
98
|
+
|
99
|
+
# Extending surveyor
|
100
|
+
def surveyor_default_finish
|
101
|
+
# http://www.postal-code.com/mrhappy/blog/2007/02/01/ruby-comparing-an-objects-class-in-a-case-statement/
|
102
|
+
# http://www.skorks.com/2009/08/how-a-ruby-case-statement-works-and-what-you-can-do-with-it/
|
103
|
+
case finish = Surveyor::Config['default.finish']
|
104
|
+
when String
|
105
|
+
return finish
|
106
|
+
when Symbol
|
107
|
+
return self.send(finish)
|
108
|
+
else
|
109
|
+
return '/surveys'
|
110
|
+
end
|
111
|
+
end
|
112
|
+
def extend_actions
|
113
|
+
# http://blog.mattwynne.net/2009/07/11/rails-tip-use-polymorphism-to-extend-your-controllers-at-runtime/
|
114
|
+
self.extend SurveyorControllerExtensions::Actions if Surveyor::Config['extend_controller'] && defined? SurveyorControllerExtensions::Actions
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class SurveyFormBuilder < ActionView::Helpers::FormBuilder
|
2
|
+
def survey_check_box(method, options = {}, checked_value = "1", unchecked_value = "0")
|
3
|
+
fields = @template.survey_check_box(@object_name, method, options.merge(:object => @object), checked_value, unchecked_value)
|
4
|
+
fields[1]
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
module ActionView
|
9
|
+
module Helpers
|
10
|
+
module FormHelper
|
11
|
+
def survey_check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
|
12
|
+
if (Rails::VERSION::STRING.to_f > 2.1)
|
13
|
+
InstanceTag.new(object_name, method, self, options.delete(:object)).to_survey_check_box_tag(options, checked_value, unchecked_value)
|
14
|
+
else
|
15
|
+
InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_survey_check_box_tag(options, checked_value, unchecked_value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class InstanceTag
|
21
|
+
def to_survey_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0")
|
22
|
+
options = options.stringify_keys
|
23
|
+
options["type"] = "checkbox"
|
24
|
+
options["value"] = checked_value
|
25
|
+
if options.has_key?("checked")
|
26
|
+
cv = options.delete "checked"
|
27
|
+
checked = cv == true || cv == "checked"
|
28
|
+
else
|
29
|
+
checked = self.class.check_box_checked?(value(object), checked_value)
|
30
|
+
end
|
31
|
+
options["checked"] = "checked" if checked
|
32
|
+
add_default_name_and_id(options)
|
33
|
+
[tag("input", "name" => options["name"], "type" => "hidden", "value" => unchecked_value), tag("input", options)]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module SurveyorHelper
|
2
|
+
|
3
|
+
# Configuration
|
4
|
+
def surveyor_config
|
5
|
+
Surveyor::Config
|
6
|
+
end
|
7
|
+
|
8
|
+
# Layout: stylsheets and javascripts
|
9
|
+
def surveyor_includes
|
10
|
+
surveyor_stylsheets + surveyor_javascripts
|
11
|
+
end
|
12
|
+
def surveyor_stylsheets
|
13
|
+
stylesheet_link_tag 'surveyor/reset', 'surveyor/surveyor', 'surveyor/ui.theme.css','surveyor/jquery-ui-slider-additions'
|
14
|
+
end
|
15
|
+
def surveyor_javascripts
|
16
|
+
javascript_include_tag 'surveyor/jquery-1.2.6.js', 'surveyor/jquery-ui-personalized-1.5.3.js', 'surveyor/accessibleUISlider.jQuery.js','surveyor/jquery.form.js', 'surveyor/surveyor.js'
|
17
|
+
end
|
18
|
+
|
19
|
+
# Section: dependencies, menu, previous and next
|
20
|
+
def dependency_explanation_helper(question,response_set)
|
21
|
+
# Attempts to explain why this dependent question needs to be answered by referenced the dependent question and users response
|
22
|
+
trigger_responses = []
|
23
|
+
dependent_questions = Question.find_all_by_id(question.dependency.dependency_conditions.map(&:question_id)).uniq
|
24
|
+
response_set.responses.find_all_by_question_id(dependent_questions.map(&:id)).uniq.each do |resp|
|
25
|
+
trigger_responses << resp.to_s
|
26
|
+
end
|
27
|
+
" You answered "#{trigger_responses.join("" and "")}" to the question "#{dependent_questions.map(&:text).join("","")}""
|
28
|
+
end
|
29
|
+
def menu_button_for(section)
|
30
|
+
submit_tag(section.title, :name => "section[#{section.id}]")
|
31
|
+
end
|
32
|
+
def previous_section
|
33
|
+
# submit_tag("« Previous section", :name => "section[#{@section.previous.id}]") unless @section.previous.nil?
|
34
|
+
# refactored to use copy in memory instead of making extra db calls
|
35
|
+
submit_tag("« Previous section", :name => "section[#{@sections[@sections.index(@section)-1].id}]") unless @sections.first == @section
|
36
|
+
end
|
37
|
+
def next_section
|
38
|
+
# @section.next.nil? ? submit_tag("Click here to finish", :name => "finish") : submit_tag("Next section »", :name => "section[#{@section.next.id}]")
|
39
|
+
# refactored to use copy in memory instead of making extra db calls
|
40
|
+
@sections.last == @section ? submit_tag("Click here to finish", :name => "finish") : submit_tag("Next section »", :name => "section[#{@sections[@sections.index(@section)+1].id}]")
|
41
|
+
end
|
42
|
+
|
43
|
+
# Questions
|
44
|
+
def next_number
|
45
|
+
@n ||= 0
|
46
|
+
"#{@n += 1}<span style='padding-left:0.1em;'>)</span>"
|
47
|
+
end
|
48
|
+
def split_text(text = "") # Split text into with "|" delimiter - parts to go before/after input element
|
49
|
+
{:prefix => text.split("|")[0].blank? ? " " : text.split("|")[0], :postfix => text.split("|")[1] || " "}
|
50
|
+
end
|
51
|
+
def question_help_helper(question)
|
52
|
+
question.help_text.blank? ? "" : %Q(<span class="question-help">#{question.help_text}</span>)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Answers
|
56
|
+
def fields_for_response(response, &block)
|
57
|
+
fields_for("responses[#{response.question_id}][#{response.answer_id}]", response, :builder => SurveyFormBuilder, &block)
|
58
|
+
end
|
59
|
+
def fields_for_repeater_response(response, response_group, &block) # Changes the response hash to accept response groups for repeater elements
|
60
|
+
fields_for("response_groups[#{response.question_id}][#{response_group}][#{response.answer_id}]", response, :builder => SurveyFormBuilder, &block)
|
61
|
+
end
|
62
|
+
def fields_for_radio(response, &block)
|
63
|
+
fields_for("responses[#{response.question_id}]", response, :builder => SurveyFormBuilder, &block)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Answer < ActiveRecord::Base
|
2
|
+
|
3
|
+
# Associations
|
4
|
+
belongs_to :question
|
5
|
+
has_many :responses
|
6
|
+
|
7
|
+
# Scopes
|
8
|
+
default_scope :order => "display_order ASC"
|
9
|
+
|
10
|
+
# Validations
|
11
|
+
validates_presence_of :text
|
12
|
+
validates_numericality_of :question_id, :allow_nil => false, :only_integer => true
|
13
|
+
#validates_uniqueness_of :reference_identifier
|
14
|
+
|
15
|
+
# Methods
|
16
|
+
def renderer(q = question)
|
17
|
+
r = [q.pick.to_s, self.response_class].compact.join("_")
|
18
|
+
r.blank? ? :default : r.to_sym
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Dependency < ActiveRecord::Base
|
2
|
+
# Associations
|
3
|
+
belongs_to :question
|
4
|
+
has_many :dependency_conditions
|
5
|
+
|
6
|
+
# Scopes
|
7
|
+
named_scope :depending_on_questions, lambda {|question_ids| {:include => :dependency_conditions, :conditions => {:dependency_conditions => {:question_id => question_ids}} }}
|
8
|
+
|
9
|
+
# Validations
|
10
|
+
validates_presence_of :rule
|
11
|
+
validates_format_of :rule, :with => /^(?:and|or|\)|\(|\d|\s)+$/ #TODO properly formed parenthesis etc.
|
12
|
+
validates_numericality_of :question_id
|
13
|
+
|
14
|
+
# Attribute aliases
|
15
|
+
alias_attribute :dependent_question_id, :question_id
|
16
|
+
|
17
|
+
# Is the method that determines if this dependency has been met within
|
18
|
+
# the provided response set
|
19
|
+
def met?(response_set)
|
20
|
+
if keyed_pairs = keyed_conditions(response_set)
|
21
|
+
return(rule_evaluation(keyed_pairs))
|
22
|
+
else
|
23
|
+
return(false)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Pairs up the substitution key with the evaluated condition result for substitution into the rule
|
28
|
+
# Example: If you have two dependency conditions with rule keys "A" and "B" in the rule "A or B"
|
29
|
+
# calling keyed_condition_pairs will return {:A => true, :B => false}
|
30
|
+
def keyed_conditions(response_set)
|
31
|
+
keyed_pairs = {}
|
32
|
+
self.dependency_conditions.each do |dc|
|
33
|
+
keyed_pairs.merge!(dc.to_evaluation_hash(response_set))
|
34
|
+
end
|
35
|
+
return(keyed_pairs)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Does the substiution and evaluation of the dependency rule with the keyed pairs
|
39
|
+
def rule_evaluation(keyed_pairs)
|
40
|
+
# subtitute into rule for evaluation
|
41
|
+
rgx = Regexp.new(self.dependency_conditions.map{|dc| dc.rule_key}.join("|")) # Making a regexp to only look for the keys used in the child conditions
|
42
|
+
#logger.debug("rexp: #{rgx.inspect} FOO: #{keyed_pairs.inspect} --- subbed rules: #{rule.gsub(rgx){|m| keyed_pairs[m.to_sym]}} --> #{eval(self.rule.gsub(rgx){|m| keyed_pairs[m.to_sym]})}")
|
43
|
+
eval(self.rule.gsub(rgx){|m| keyed_pairs[m.to_sym]}) # returns the evaluation of the rule and the conditions
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|