jakewendt-surveyor 0.11.3
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +285 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/app/controllers/surveyor_controller.rb +142 -0
- data/app/helpers/survey_form_builder.rb +37 -0
- data/app/helpers/surveyor_helper.rb +67 -0
- data/app/models/answer.rb +23 -0
- data/app/models/dependency.rb +50 -0
- data/app/models/dependency_condition.rb +47 -0
- data/app/models/question.rb +54 -0
- data/app/models/question_group.rb +33 -0
- data/app/models/response.rb +94 -0
- data/app/models/response_set.rb +316 -0
- data/app/models/survey.rb +172 -0
- data/app/models/survey_section.rb +18 -0
- data/app/models/validation.rb +38 -0
- data/app/models/validation_condition.rb +47 -0
- data/app/views/layouts/surveyor_default.html.erb +13 -0
- data/app/views/partials/_answer.html.haml +58 -0
- data/app/views/partials/_question.html.haml +80 -0
- data/app/views/partials/_question_group.html.haml +39 -0
- data/app/views/surveyor/edit.html.haml +38 -0
- data/app/views/surveyor/new.html.haml +16 -0
- data/app/views/surveyor/show.html.haml +12 -0
- data/config/routes.rb +11 -0
- data/features/step_definitions/surveyor_steps.rb +7 -0
- data/features/step_definitions/web_steps.rb +273 -0
- data/features/support/env.rb +57 -0
- data/features/support/paths.rb +25 -0
- data/features/surveyor.feature +11 -0
- data/generators/extend_surveyor/extend_surveyor_generator.rb +22 -0
- data/generators/extend_surveyor/templates/EXTENDING_SURVEYOR +17 -0
- data/generators/extend_surveyor/templates/extensions/survey_extensions.rb +24 -0
- data/generators/extend_surveyor/templates/extensions/surveyor_controller_extensions.rb +28 -0
- data/generators/extend_surveyor/templates/extensions/surveyor_custom.html.erb +13 -0
- data/generators/extend_surveyor/templates/extensions/surveyor_helper_extensions.rb +17 -0
- data/generators/surveyor/surveyor_generator.rb +67 -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 +47 -0
- data/generators/surveyor/templates/assets/stylesheets/jquery-ui-slider-additions.css +71 -0
- data/generators/surveyor/templates/assets/stylesheets/reset.css +50 -0
- data/generators/surveyor/templates/assets/stylesheets/sass/surveyor.sass +243 -0
- data/generators/surveyor/templates/assets/stylesheets/surveyor.css +235 -0
- data/generators/surveyor/templates/assets/stylesheets/ui.theme.css +851 -0
- data/generators/surveyor/templates/initializers/haml.rb +8 -0
- data/generators/surveyor/templates/initializers/surveyor.rb +10 -0
- data/generators/surveyor/templates/migrate/add_correct_answer_id_to_questions.rb +9 -0
- data/generators/surveyor/templates/migrate/add_display_order_to_surveys.rb +9 -0
- data/generators/surveyor/templates/migrate/add_index_to_response_sets.rb +9 -0
- data/generators/surveyor/templates/migrate/add_index_to_surveys.rb +9 -0
- data/generators/surveyor/templates/migrate/add_manual_numbering.rb +11 -0
- data/generators/surveyor/templates/migrate/add_unique_indicies.rb +17 -0
- data/generators/surveyor/templates/migrate/create_answers.rb +37 -0
- data/generators/surveyor/templates/migrate/create_dependencies.rb +22 -0
- data/generators/surveyor/templates/migrate/create_dependency_conditions.rb +29 -0
- data/generators/surveyor/templates/migrate/create_question_groups.rb +27 -0
- data/generators/surveyor/templates/migrate/create_questions.rb +36 -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 +29 -0
- data/generators/surveyor/templates/migrate/create_surveys.rb +31 -0
- data/generators/surveyor/templates/migrate/create_validation_conditions.rb +32 -0
- data/generators/surveyor/templates/migrate/create_validations.rb +20 -0
- data/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +218 -0
- data/generators/surveyor/templates/tasks/surveyor.rb +4 -0
- data/generators/test_surveyor/templates/TESTING_SURVEYOR +0 -0
- data/generators/test_surveyor/templates/environments/cucumber.rb +21 -0
- data/generators/test_surveyor/test_surveyor_generator.rb +15 -0
- data/jakewendt-surveyor.gemspec +212 -0
- data/lib/fixtures_extensions.rb +6 -0
- data/lib/jakewendt-surveyor.rb +1 -0
- data/lib/surveyor.rb +44 -0
- data/lib/surveyor/acts_as_response.rb +33 -0
- data/lib/surveyor/config.rb +45 -0
- data/lib/tasks/surveyor_tasks.rake +33 -0
- data/lib/xml_formatter.rb +12 -0
- data/rails/init.rb +1 -0
- data/script/surveyor/answer.rb +54 -0
- data/script/surveyor/base.rb +77 -0
- data/script/surveyor/dependency.rb +13 -0
- data/script/surveyor/dependency_condition.rb +40 -0
- data/script/surveyor/parser.rb +207 -0
- data/script/surveyor/question.rb +37 -0
- data/script/surveyor/question_group.rb +26 -0
- data/script/surveyor/specs/answer_spec.rb +29 -0
- data/script/surveyor/specs/question_spec.rb +63 -0
- data/script/surveyor/specs/spec_helper.rb +7 -0
- data/script/surveyor/specs/survey_section_spec.rb +23 -0
- data/script/surveyor/specs/validation_condition_spec.rb +20 -0
- data/script/surveyor/specs/validation_spec.rb +20 -0
- data/script/surveyor/survey.rb +35 -0
- data/script/surveyor/survey_section.rb +21 -0
- data/script/surveyor/validation.rb +21 -0
- data/script/surveyor/validation_condition.rb +21 -0
- data/script/surveyor/whr_dsl.tmproj +244 -0
- data/spec/controllers/surveyor_controller_spec.rb +193 -0
- data/spec/factories.rb +145 -0
- data/spec/lib/surveyor_spec.rb +44 -0
- data/spec/models/answer_spec.rb +29 -0
- data/spec/models/dependency_condition_spec.rb +321 -0
- data/spec/models/dependency_spec.rb +81 -0
- data/spec/models/question_group_spec.rb +35 -0
- data/spec/models/question_spec.rb +75 -0
- data/spec/models/response_set_spec.rb +245 -0
- data/spec/models/response_spec.rb +76 -0
- data/spec/models/survey_section_spec.rb +32 -0
- data/spec/models/survey_spec.rb +71 -0
- data/spec/models/validation_condition_spec.rb +105 -0
- data/spec/models/validation_spec.rb +59 -0
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +12 -0
- metadata +254 -0
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,285 @@
|
|
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
|
+
## Why you might want to use Surveyor
|
6
|
+
|
7
|
+
If you have to have a part of your Rails app that asks users questions as part of a survey, quiz, or questionnaire then you should consider using Surveyor. This plugin was designed out of the need to deliver clinical research surveys to large populations of people but it can be used for any type of survey. It has an easy to use DSL to define the questions, response dependencies (if user answers 'A' to question 1 then show question 1a, etc...), and structure (different sections of longer questionnaires).
|
8
|
+
|
9
|
+
To build your questionnaire you define it using a custom DSL. Having a DSL instead of a GUI makes it significantly easier to import long surveys (no more endless clicking and typing into tiny text boxes). It also means that you can let your customer write out the survey, edit, re-edit, tweak, throw out and start over, any number of surveys without having to change a single line of code in your app.
|
10
|
+
|
11
|
+
## DSL example
|
12
|
+
|
13
|
+
Our DSL supports a wide range of question types (too many to list here) and varying dependency logic. Here are the first few questions of the "kitchen_sink" survey which should give you and idea of how the DSL works. The full example with all the types of questions is in the plugin and available if you run the installation instructions below.
|
14
|
+
|
15
|
+
survey "“Kitchen Sink” survey" do
|
16
|
+
|
17
|
+
section "Basic questions" do
|
18
|
+
# A label is a question that accepts no answers
|
19
|
+
label "These questions are examples of the basic supported input types"
|
20
|
+
|
21
|
+
# A basic question with radio buttons
|
22
|
+
question_1 "What is your favorite color?", :pick => :one
|
23
|
+
answer "red"
|
24
|
+
answer "blue"
|
25
|
+
answer "green"
|
26
|
+
answer "yellow"
|
27
|
+
answer :other
|
28
|
+
|
29
|
+
# A basic question with checkboxes
|
30
|
+
# "question" and "answer" may be abbreviated as "q" and "a"
|
31
|
+
q_2 "Choose the colors you don't like", :pick => :any
|
32
|
+
a_1 "red"
|
33
|
+
a_2 "blue"
|
34
|
+
a_3 "green"
|
35
|
+
a_4 "yellow"
|
36
|
+
a :omit
|
37
|
+
|
38
|
+
# A dependent question, with conditions and rule to logically join them
|
39
|
+
# the question's reference identifier is "2a", and the answer's reference_identifier is "1"
|
40
|
+
# question reference identifiers used in conditions need to be unique on a survey for the lookups to work
|
41
|
+
q_2a "Please explain why you don't like this color?"
|
42
|
+
a_1 "explanation", :text
|
43
|
+
dependency :rule => "A or B or C or D"
|
44
|
+
condition_A :q_2, "==", :a_1
|
45
|
+
condition_B :q_2, "==", :a_2
|
46
|
+
condition_C :q_2, "==", :a_3
|
47
|
+
condition_D :q_2, "==", :a_4
|
48
|
+
|
49
|
+
# ... other question, sections and such. See kitchen_sink_survey.rb for more.
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
The survey above shows a couple simple question types. The first one is a "pick one" type with the "other" custom entry. The second question is a "pick any" type with the option to "omit". It also has a dependency where you can ask a follow up question based on how the user answered the previous question. Notice the way the dependency is defined as a string. This implementation supports any number of complex dependency rules so not just "A or B or C or D" but "A and (B or C) and D" or "!A or ((B and !C) or D)". The conditions are the letters used they are evaluated separately using the operators defined for "==","<>", ">=","<", (the usual stuff) the plugged in to the dependency rule and evaluated. See the example survey for more details.
|
55
|
+
|
56
|
+
# Installation
|
57
|
+
|
58
|
+
As a plugin:
|
59
|
+
|
60
|
+
gem install haml
|
61
|
+
script/plugin install git://github.com/breakpointer/surveyor.git -r 'tag v0.10.0'
|
62
|
+
|
63
|
+
Or as a gem plugin:
|
64
|
+
|
65
|
+
# in environment.rb
|
66
|
+
config.gem "surveyor", :version => '~> 0.10.0', :source => 'http://gemcutter.org'
|
67
|
+
|
68
|
+
rake gems:install
|
69
|
+
|
70
|
+
Generate assets, run migrations:
|
71
|
+
|
72
|
+
script/generate surveyor
|
73
|
+
rake db:migrate
|
74
|
+
|
75
|
+
Try out the "kitchen sink" survey:
|
76
|
+
|
77
|
+
rake surveyor FILE=surveys/kitchen_sink_survey.rb
|
78
|
+
|
79
|
+
The rake surveyor task overwrites previous surveys by default, but can append instead:
|
80
|
+
|
81
|
+
rake surveyor FILE=surveys/kitchen_sink_survey.rb APPEND=true
|
82
|
+
|
83
|
+
The rake tasks above generate surveys in our custom survey DSL (which is a great format for end users and stakeholders to use).
|
84
|
+
After you have run them start up your app:
|
85
|
+
|
86
|
+
script/server
|
87
|
+
|
88
|
+
(or however you normally start your app) and goto:
|
89
|
+
|
90
|
+
http://localhost:3000/surveys
|
91
|
+
|
92
|
+
Try taking the survey and compare it to the contents of the DSL file kitchen\_sink\_survey.rb. See how each type of
|
93
|
+
DSL question maps to the resulting rendered view of the question.
|
94
|
+
|
95
|
+
# Configuration
|
96
|
+
|
97
|
+
The surveyor generator creates config/initializers/surveyor.rb. There, you can specify:
|
98
|
+
|
99
|
+
- your own relative root for surveys ('/' is not recommended as any path will be interpreted as a survey name)
|
100
|
+
- your own custom title (string) for the survey list page
|
101
|
+
- your own custom layout file name, in your app/views/layouts folder
|
102
|
+
- your own custom finish url for all surveys. you can give a string (a path), a symbol (the name of a method in ApplicationController)
|
103
|
+
- if you would like surveys to require authorization via the restful_authentication plugin
|
104
|
+
- if you would like to extend the surveyor_controller (see Extending Surveyor below)
|
105
|
+
|
106
|
+
The initializer runs once, when the app starts. The block style is used to keep multiple options DRY (defaults below):
|
107
|
+
|
108
|
+
Surveyor::Config.run do |config|
|
109
|
+
config['default.relative_url_root'] = nil # "surveys"
|
110
|
+
config['default.title'] = nil # "You can take these surveys:"
|
111
|
+
config['default.layout'] = nil # "surveyor_default"
|
112
|
+
config['default.index'] = nil # "/surveys" # or :index_path_method
|
113
|
+
config['default.finish'] = nil # "/surveys" # or :finish_path_method
|
114
|
+
#config['authentication_method'] = :login_required # set to true to use restful authentication
|
115
|
+
config['extend'] = %w() # %w(survey surveyor_helper surveyor_controller)
|
116
|
+
end
|
117
|
+
|
118
|
+
You can update surveyor's configuration at any time. Use the block style (above), or the individual style:
|
119
|
+
|
120
|
+
Surveyor::Config['default.title'] = "Cheese is great!"
|
121
|
+
|
122
|
+
To look at the current surveyor configuration:
|
123
|
+
|
124
|
+
Surveyor::Config.to_hash.inspect
|
125
|
+
|
126
|
+
# Extending surveyor
|
127
|
+
|
128
|
+
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:
|
129
|
+
|
130
|
+
script/generate extend_surveyor
|
131
|
+
|
132
|
+
Any of surveyor's models class_eval, class methods, and instance methods can be modified. Include the following in config/initializers/surveyor.rb:
|
133
|
+
|
134
|
+
require 'models/survey_extensions' # Extended the survey model
|
135
|
+
|
136
|
+
SurveyorHelper class_eval and instance methods can be modified. Include the following in config/initializers/surveyor.rb:
|
137
|
+
|
138
|
+
require 'helpers/surveyor_helper_extensions' # Extend the surveyor helper
|
139
|
+
|
140
|
+
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:
|
141
|
+
|
142
|
+
config['extend_controller'] = true
|
143
|
+
|
144
|
+
# Sample layout
|
145
|
+
|
146
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
147
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
148
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
149
|
+
<head>
|
150
|
+
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
|
151
|
+
<title>Survey: <%= controller.action_name %></title>
|
152
|
+
<%= surveyor_includes %>
|
153
|
+
</head>
|
154
|
+
<body>
|
155
|
+
<div id="flash"><%= flash[:notice] %></div>
|
156
|
+
<%= yield %>
|
157
|
+
</body>
|
158
|
+
</html>
|
159
|
+
|
160
|
+
The <code>surveyor\_includes</code> helper just calls <code>surveyor\_stylsheets + surveyor\_javascripts</code> which in turn call:
|
161
|
+
|
162
|
+
stylesheet_link_tag 'surveyor/reset', 'surveyor/surveyor', 'surveyor/ui.theme.css','surveyor/jquery-ui-slider-additions'
|
163
|
+
|
164
|
+
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'
|
165
|
+
|
166
|
+
# Dependencices
|
167
|
+
|
168
|
+
Surveyor depends on Rails 2.3 and the SASS style sheet language, part of HAML (http://haml.hamptoncatlin.com/download). For running the test suite you will need rspec and have the rspec plugin installed in your application.
|
169
|
+
|
170
|
+
# Test Suite and Development
|
171
|
+
|
172
|
+
To work on the plugin code (for enhancements, and bug fixes, etc...) fork this github project. Then clone the project under the vendor/plugins directory in a Rails app used only for development:
|
173
|
+
|
174
|
+
|
175
|
+
# Changes
|
176
|
+
|
177
|
+
0.11.0
|
178
|
+
|
179
|
+
* basic csv export. closes #21
|
180
|
+
* add unique indicies. closes #45
|
181
|
+
* add one_integer renderer. closes #51
|
182
|
+
* constrain surveys to have unique access_codes. closes #45. closes #42
|
183
|
+
* covering the extremely unlikely case that response_sets may have a non-unique access_code. closes #46. thanks jakewendt.
|
184
|
+
* current user id not needed in the view, set in SurveyorController. closes #48. thanks jakewendt
|
185
|
+
|
186
|
+
0.10.0
|
187
|
+
|
188
|
+
* surveyor config['extend'] is now an array. custom modules (e.g. SurveyExtensions are now included from within surveyor models, allowing
|
189
|
+
the customizations to work on every request in development. closes #39. thanks to mgurley and jakewendt for the suggestions.
|
190
|
+
* remove comment from surveyor_includes
|
191
|
+
* css tweak
|
192
|
+
* automatically add backslashes and eliminate multiple backslashes in relative root for routes
|
193
|
+
* readme spelling and line breaks
|
194
|
+
* fixing a failing spec with factory instead of mock parent model
|
195
|
+
* upgrading cucumber to 0.6
|
196
|
+
|
197
|
+
0.9.11
|
198
|
+
|
199
|
+
* adding rails init.rb to make gem loading work. thanks mike gurley. closes #52.
|
200
|
+
* Repeater changed to only have +1, not +3 as previous
|
201
|
+
* added locking and transaction to surveyor update action. Prevents bug that caused duplicated answers
|
202
|
+
* some light re-factoring and code readability changes
|
203
|
+
* some code formatting changes
|
204
|
+
* added require statement to specs so the factory_girl test dependency was more clear
|
205
|
+
* spiced up the readme... may have some typos
|
206
|
+
* readme update
|
207
|
+
|
208
|
+
0.9.10
|
209
|
+
|
210
|
+
* styles, adding labels for dates, correcting labels for radio buttons
|
211
|
+
|
212
|
+
0.9.9
|
213
|
+
|
214
|
+
* count label and image questions complete when mandatory. closes #38
|
215
|
+
* validate by other responses. closes #35
|
216
|
+
|
217
|
+
0.9.8
|
218
|
+
|
219
|
+
* @current\_user.id if @current\_user isn't nil. Closes #37
|
220
|
+
|
221
|
+
0.9.7
|
222
|
+
|
223
|
+
* fixing typos
|
224
|
+
* remove surveyor controller from load\_once\_paths. fixes issue with dependencies and unloading in development. closes #36
|
225
|
+
|
226
|
+
0.9.6
|
227
|
+
|
228
|
+
* response set reports progress and mandatory questions completeness. closes #33
|
229
|
+
* adding correctness to response sets
|
230
|
+
* adding correctness to responses
|
231
|
+
|
232
|
+
0.9.5
|
233
|
+
|
234
|
+
* allow append for survey parser. closes #32
|
235
|
+
|
236
|
+
0.9.4
|
237
|
+
|
238
|
+
* making tinycode compatible with ruby 1.8.6
|
239
|
+
|
240
|
+
0.9.3
|
241
|
+
|
242
|
+
* fix for survey parser require
|
243
|
+
|
244
|
+
0.9.2
|
245
|
+
|
246
|
+
* fixing specs for namespacing and move of tinycode
|
247
|
+
* namespacing SurveyParser models to avoid conflict with model extensions
|
248
|
+
|
249
|
+
0.9.1
|
250
|
+
|
251
|
+
* fix for tinycode, more descriptive missing method
|
252
|
+
|
253
|
+
0.9.0
|
254
|
+
|
255
|
+
* validations in dsl and surveyor models
|
256
|
+
* preserve underscores in reference identifiers
|
257
|
+
* dsl specs, refactoring into base class
|
258
|
+
* adding display order to surveys
|
259
|
+
* moving columnizer and tiny column functionality to surveyor module
|
260
|
+
* columnizer (and tiny code) refactoring, columnizer spec extracted from answer spec
|
261
|
+
* cleanup of scopes with joins
|
262
|
+
* refactoring dependency
|
263
|
+
|
264
|
+
0.8.0
|
265
|
+
|
266
|
+
* question group dependencies
|
267
|
+
* expanded examples in kitchen sink survey
|
268
|
+
* specs
|
269
|
+
|
270
|
+
0.7.1
|
271
|
+
|
272
|
+
* custom index page
|
273
|
+
* custom classes and renderers
|
274
|
+
* fixing typo in kitchen sink survey
|
275
|
+
|
276
|
+
0.7.0
|
277
|
+
|
278
|
+
* new kitchen sink survey with better documentation of DSL
|
279
|
+
* migration misspelling
|
280
|
+
* fixing ordering, dependency conditions evaluation, and changing named scopes for now
|
281
|
+
* DRYing up surveyor DSL models
|
282
|
+
* working on adding dependencies for question groups
|
283
|
+
|
284
|
+
|
285
|
+
Copyright (c) 2008-2009 Brian Chamberlain and Mark Yoon, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "jakewendt-surveyor"
|
8
|
+
gem.summary = %Q{A rails (gem) plugin to enable surveys in your application}
|
9
|
+
gem.email = "github@jake.otherinbox.com"
|
10
|
+
gem.homepage = "http://github.com/jakewendt/surveyor"
|
11
|
+
gem.authors = ["Brian Chamberlain", "Mark Yoon",'Jake Wendt']
|
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
|
+
begin
|
22
|
+
require 'spec/rake/spectask'
|
23
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
24
|
+
spec.libs << 'lib' << 'spec'
|
25
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
26
|
+
end
|
27
|
+
|
28
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
29
|
+
spec.libs << 'lib' << 'spec'
|
30
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
31
|
+
spec.rcov = true
|
32
|
+
end
|
33
|
+
rescue LoadError
|
34
|
+
puts "RSpec is not available. In order to run those tasks, you must: sudo gem install rspec"
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
task :default => :spec
|
39
|
+
|
40
|
+
require 'rake/rdoctask'
|
41
|
+
Rake::RDocTask.new do |rdoc|
|
42
|
+
if File.exist?('VERSION.yml')
|
43
|
+
config = YAML.load(File.read('VERSION.yml'))
|
44
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
45
|
+
else
|
46
|
+
version = ""
|
47
|
+
end
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "surveyor #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
54
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.11.3
|
@@ -0,0 +1,142 @@
|
|
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'].include?("surveyor_controller")
|
11
|
+
before_filter :extend_actions
|
12
|
+
|
13
|
+
# RESTful authentication
|
14
|
+
if Surveyor::Config['authentication_method']
|
15
|
+
before_filter Surveyor::Config['authentication_method']
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get the response set or current_user
|
19
|
+
# before_filter :get_response_set, :except => [:new, :create]
|
20
|
+
before_filter :get_current_user, :only => [:new, :create]
|
21
|
+
|
22
|
+
# Actions
|
23
|
+
def new
|
24
|
+
@surveys = Survey.find(:all)
|
25
|
+
redirect_to surveyor_default(:index) unless available_surveys_path == surveyor_default(:index)
|
26
|
+
end
|
27
|
+
|
28
|
+
def create
|
29
|
+
@survey = Survey.find_by_access_code(params[:survey_code])
|
30
|
+
@response_set = ResponseSet.create(:survey => @survey, :user_id => (@current_user.nil? ? @current_user : @current_user.id))
|
31
|
+
if (@survey && @response_set)
|
32
|
+
flash[:notice] = "Survey was successfully started."
|
33
|
+
redirect_to(edit_my_survey_path(:survey_code => @survey.access_code, :response_set_code => @response_set.access_code))
|
34
|
+
else
|
35
|
+
flash[:notice] = "Unable to find that survey"
|
36
|
+
redirect_to(available_surveys_path)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def show
|
41
|
+
@response_set = ResponseSet.find_by_access_code(params[:response_set_code], :include => {:responses => [:question, :answer]})
|
42
|
+
respond_to do |format|
|
43
|
+
format.html #{render :action => :show}
|
44
|
+
format.csv {
|
45
|
+
send_data(@response_set.to_csv, :type => 'text/csv; charset=utf-8; header=present',:filename => "#{@response_set.updated_at.strftime('%Y-%m-%d')}_#{@response_set.access_code}.csv")
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def edit
|
51
|
+
@response_set = ResponseSet.find_by_access_code(params[:response_set_code], :include => {:responses => [:question, :answer]})
|
52
|
+
if @response_set
|
53
|
+
@survey = Survey.with_sections.find_by_id(@response_set.survey_id)
|
54
|
+
@sections = @survey.sections
|
55
|
+
if params[:section]
|
56
|
+
@section = @sections.with_includes.find(section_id_from(params[:section])) || @sections.with_includes.first
|
57
|
+
else
|
58
|
+
@section = @sections.with_includes.first
|
59
|
+
end
|
60
|
+
@questions = @section.questions
|
61
|
+
@dependents = (@response_set.unanswered_dependencies - @section.questions) || []
|
62
|
+
else
|
63
|
+
flash[:notice] = "Unable to find your responses to the survey"
|
64
|
+
redirect_to(available_surveys_path)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def update
|
69
|
+
saved = nil
|
70
|
+
ActiveRecord::Base.transaction do
|
71
|
+
if @response_set = ResponseSet.find_by_access_code(params[:response_set_code], :include => {:responses => :answer},:lock => true)
|
72
|
+
@response_set.current_section_id = params[:current_section_id]
|
73
|
+
else
|
74
|
+
flash[:notice] = "Unable to find your responses to the survey"
|
75
|
+
redirect_to(available_surveys_path) and return
|
76
|
+
end
|
77
|
+
|
78
|
+
if params[:responses] or params[:response_groups]
|
79
|
+
@response_set.clear_responses
|
80
|
+
saved = @response_set.update_attributes(:response_attributes => (params[:responses] || {}).dup ,
|
81
|
+
:response_group_attributes => (params[:response_groups] || {}).dup) #copy (dup) to preserve params because we manipulate params in the response_set methods
|
82
|
+
if (saved && params[:finish])
|
83
|
+
@response_set.complete!
|
84
|
+
saved = @response_set.save!
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
respond_to do |format|
|
89
|
+
format.html do
|
90
|
+
if saved && params[:finish]
|
91
|
+
flash[:notice] = "Completed survey"
|
92
|
+
redirect_to surveyor_default(:finish)
|
93
|
+
else
|
94
|
+
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)
|
95
|
+
redirect_to :action => "edit", :anchor => anchor_from(params[:section]), :params => {:section => section_id_from(params[:section])}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
# No redirect needed if we're talking to the page via json
|
99
|
+
format.js do
|
100
|
+
# render :json => @response_set.all_dependencies.to_json
|
101
|
+
render :json => @response_set.all_things_hash.to_json
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
# Filters
|
109
|
+
def get_current_user
|
110
|
+
@current_user = self.respond_to?(:current_user) ? self.current_user : nil
|
111
|
+
end
|
112
|
+
|
113
|
+
# 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
|
114
|
+
# e.g. params[:section] = {"1"=>{"question_group_1"=>"<= add row"}}
|
115
|
+
def section_id_from(p)
|
116
|
+
p.respond_to?(:keys) ? p.keys.first : p
|
117
|
+
end
|
118
|
+
|
119
|
+
def anchor_from(p)
|
120
|
+
p.respond_to?(:keys) && p[p.keys.first].respond_to?(:keys) ? p[p.keys.first].keys.first : nil
|
121
|
+
end
|
122
|
+
|
123
|
+
# Extending surveyor
|
124
|
+
def surveyor_default(type = :finish)
|
125
|
+
# http://www.postal-code.com/mrhappy/blog/2007/02/01/ruby-comparing-an-objects-class-in-a-case-statement/
|
126
|
+
# http://www.skorks.com/2009/08/how-a-ruby-case-statement-works-and-what-you-can-do-with-it/
|
127
|
+
case arg = Surveyor::Config["default.#{type.to_s}"]
|
128
|
+
when String
|
129
|
+
return arg
|
130
|
+
when Symbol
|
131
|
+
return self.send(arg)
|
132
|
+
else
|
133
|
+
return available_surveys_path
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def extend_actions
|
138
|
+
# http://blog.mattwynne.net/2009/07/11/rails-tip-use-polymorphism-to-extend-your-controllers-at-runtime/
|
139
|
+
self.extend SurveyorControllerExtensions::Actions if Surveyor::Config['extend'].include?("surveyor_controller") && defined? SurveyorControllerExtensions::Actions
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|