surveyor 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +30 -11
- data/VERSION +1 -1
- data/app/controllers/surveyor_controller.rb +7 -0
- data/app/models/response_set.rb +22 -0
- data/app/models/survey.rb +1 -0
- data/app/views/partials/_answer.html.haml +13 -10
- data/app/views/surveyor/new.html.haml +0 -1
- data/config/routes.rb +5 -5
- data/generators/surveyor/surveyor_generator.rb +2 -1
- 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_unique_indicies.rb +17 -0
- data/spec/factories.rb +3 -1
- data/spec/models/response_set_spec.rb +27 -0
- data/surveyor.gemspec +5 -2
- metadata +6 -3
data/README.md
CHANGED
@@ -106,15 +106,16 @@ The surveyor generator creates config/initializers/surveyor.rb. There, you can s
|
|
106
106
|
The initializer runs once, when the app starts. The block style is used to keep multiple options DRY (defaults below):
|
107
107
|
|
108
108
|
Surveyor::Config.run do |config|
|
109
|
-
config['default.relative_url_root'] = "surveys
|
110
|
-
config['default.title'] = "You can take these surveys:"
|
111
|
-
config['default.layout'] = "surveyor_default"
|
112
|
-
config['default.
|
113
|
-
config['
|
114
|
-
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['use_restful_authentication'] = false # set to true to use restful authentication
|
115
|
+
config['extend'] = %w() # %w(survey surveyor_helper surveyor_controller)
|
115
116
|
end
|
116
|
-
|
117
|
-
You can update surveyor's at any time. Use the block style (above), or the individual style:
|
117
|
+
|
118
|
+
You can update surveyor's configuration at any time. Use the block style (above), or the individual style:
|
118
119
|
|
119
120
|
Surveyor::Config['default.title'] = "Cheese is great!"
|
120
121
|
|
@@ -152,9 +153,7 @@ SurveyorController class_eval, class methods, instance methods, and actions can
|
|
152
153
|
</head>
|
153
154
|
<body>
|
154
155
|
<div id="flash"><%= flash[:notice] %></div>
|
155
|
-
|
156
|
-
<%= yield %>
|
157
|
-
</div>
|
156
|
+
<%= yield %>
|
158
157
|
</body>
|
159
158
|
</html>
|
160
159
|
|
@@ -175,6 +174,26 @@ To work on the plugin code (for enhancements, and bug fixes, etc...) fork this g
|
|
175
174
|
|
176
175
|
# Changes
|
177
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
|
+
|
178
197
|
0.9.11
|
179
198
|
|
180
199
|
* adding rails init.rb to make gem loading work. thanks mike gurley. closes #52.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.11.0
|
@@ -39,6 +39,13 @@ class SurveyorController < ApplicationController
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def show
|
42
|
+
@response_set = ResponseSet.find_by_access_code(params[:response_set_code], :include => {:responses => [:question, :answer]})
|
43
|
+
respond_to do |format|
|
44
|
+
format.html #{render :action => :show}
|
45
|
+
format.csv {
|
46
|
+
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")
|
47
|
+
}
|
48
|
+
end
|
42
49
|
end
|
43
50
|
|
44
51
|
def edit
|
data/app/models/response_set.rb
CHANGED
@@ -11,6 +11,7 @@ class ResponseSet < ActiveRecord::Base
|
|
11
11
|
# Validations
|
12
12
|
validates_presence_of :survey_id
|
13
13
|
validates_associated :responses
|
14
|
+
validates_uniqueness_of :access_code
|
14
15
|
|
15
16
|
# Attributes
|
16
17
|
attr_protected :completed_at
|
@@ -30,6 +31,27 @@ class ResponseSet < ActiveRecord::Base
|
|
30
31
|
self.access_code = Surveyor.make_tiny_code
|
31
32
|
end
|
32
33
|
|
34
|
+
def access_code=(val)
|
35
|
+
while ResponseSet.find_by_access_code(val)
|
36
|
+
val = Surveyor.make_tiny_code
|
37
|
+
end
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_csv
|
42
|
+
qcols = Question.content_columns.map(&:name) - %w(created_at updated_at)
|
43
|
+
acols = Answer.content_columns.map(&:name) - %w(created_at updated_at)
|
44
|
+
rcols = Response.content_columns.map(&:name)
|
45
|
+
require 'fastercsv'
|
46
|
+
FCSV(result = "") do |csv|
|
47
|
+
csv << qcols.map{|qcol| "question.#{qcol}"} + acols.map{|acol| "answer.#{acol}"} + rcols.map{|rcol| "response.#{rcol}"}
|
48
|
+
responses.each do |response|
|
49
|
+
csv << qcols.map{|qcol| response.question.send(qcol)} + acols.map{|acol| response.answer.send(acol)} + rcols.map{|rcol| response.send(rcol)}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
result
|
53
|
+
end
|
54
|
+
|
33
55
|
def response_for(question_id, answer_id, group = nil)
|
34
56
|
found = responses.detect{|r| r.question_id == question_id && r.answer_id == answer_id && r.response_group.to_s == group.to_s}
|
35
57
|
found.blank? ? responses.new(:question_id => question_id, :answer_id => answer_id, :response_group => group) : found
|
data/app/models/survey.rb
CHANGED
@@ -16,20 +16,23 @@
|
|
16
16
|
= response_form.survey_check_box(:selected, :class => (answer.is_exclusive? ? "exclusive" : ""))
|
17
17
|
= response_form.label(:answer_id, answer.text)
|
18
18
|
= response_form.text_field(:string_value, :size => 25, :maxlength => 250)
|
19
|
-
- when :one_answer, :one_string
|
19
|
+
- when :one_answer, :one_string, :one_integer
|
20
20
|
- fields_for_radio(response_obj) do |radio_form|
|
21
21
|
= radio_form.radio_button(:answer_id, answer.id, :checked => response_obj.selected?, :title => answer.text)
|
22
|
-
= radio_form.label("answer_id_#{answer.id}", answer.text
|
23
|
-
|
24
|
-
|
22
|
+
= radio_form.label("answer_id_#{answer.id}", split_text(answer.text)[:prefix]) unless hide_label
|
23
|
+
- if renderer == :one_string
|
24
|
+
= response_form.text_field(:string_value, :size => 25, :maxlength => 250, :autocomplete => "off")
|
25
|
+
- if renderer == :one_integer
|
26
|
+
= response_form.text_field(:integer_value, :size => 5, :maxlength => 10, :autocomplete => "off")
|
27
|
+
= radio_form.label("answer_id_#{answer.id}", split_text(answer.text)[:postfix]) unless hide_label
|
25
28
|
- when :none_date
|
26
|
-
= response_form.label(:
|
29
|
+
= response_form.label(:datetime_value, split_text(answer.text)[:prefix], :class => "#{(disabled)? 'disabled' : 'enabled'}") unless hide_label
|
27
30
|
= response_form.text_field(:datetime_value)
|
28
|
-
= response_form.label(:
|
31
|
+
= response_form.label(:datetime_value, split_text(answer.text)[:postfix], :class => "#{(disabled)? 'disabled' : 'enabled'}") unless hide_label
|
29
32
|
- when :none_datetime
|
30
|
-
= response_form.label(:
|
33
|
+
= response_form.label(:datetime_value, split_text(answer.text)[:prefix], :class => "#{(disabled)? 'disabled' : 'enabled'}") unless hide_label
|
31
34
|
= response_form.datetime_select(:datetime_value, {:include_blank => true})
|
32
|
-
= response_form.label(:
|
35
|
+
= response_form.label(:datetime_value, split_text(answer.text)[:postfix], :class => "#{(disabled)? 'disabled' : 'enabled'}") unless hide_label
|
33
36
|
- when :none_float
|
34
37
|
= response_form.label(:float_value, split_text(answer.text)[:prefix]) unless hide_label
|
35
38
|
= response_form.text_field(:float_value, :size => 5, :maxlength => 10, :autocomplete => "off")
|
@@ -47,9 +50,9 @@
|
|
47
50
|
= response_form.text_area(:text_value, :cols => 80, :rows => 10)
|
48
51
|
= response_form.label(:text_value, split_text(answer.text)[:postfix]) unless hide_label
|
49
52
|
- when :none_time
|
50
|
-
= response_form.label(:
|
53
|
+
= response_form.label(:datetime_value, split_text(answer.text)[:prefix], :class => "#{(disabled)? 'disabled' : 'enabled'}") unless hide_label
|
51
54
|
= response_form.time_select(:datetime_value,{ :include_blank => true })
|
52
|
-
= response_form.label(:
|
55
|
+
= response_form.label(:datetime_value, split_text(answer.text)[:postfix], :class => "#{(disabled)? 'disabled' : 'enabled'}") unless hide_label
|
53
56
|
- else
|
54
57
|
= answer.text
|
55
58
|
|
data/config/routes.rb
CHANGED
@@ -2,10 +2,10 @@ ActionController::Routing::Routes.draw do |map|
|
|
2
2
|
root = Surveyor::Config['default.relative_url_root'] || "surveys"
|
3
3
|
root = (root << "/").gsub(/\/+/, "/")
|
4
4
|
map.with_options :controller => 'surveyor' do |s|
|
5
|
-
s.available_surveys "#{root}",
|
6
|
-
s.take_survey "#{root}:survey_code",
|
7
|
-
s.view_my_survey "#{root}:survey_code/:response_set_code",
|
8
|
-
s.edit_my_survey "#{root}:survey_code/:response_set_code/take",
|
9
|
-
s.update_my_survey "#{root}:survey_code/:response_set_code",
|
5
|
+
s.available_surveys "#{root}", :conditions => {:method => :get}, :action => "new" # GET survey list
|
6
|
+
s.take_survey "#{root}:survey_code", :conditions => {:method => :post}, :action => "create" # Only POST of survey to create
|
7
|
+
s.view_my_survey "#{root}:survey_code/:response_set_code.:format", :conditions => {:method => :get}, :action => "show", :format => "html" # GET viewable/printable? survey
|
8
|
+
s.edit_my_survey "#{root}:survey_code/:response_set_code/take", :conditions => {:method => :get}, :action => "edit" # GET editable survey
|
9
|
+
s.update_my_survey "#{root}:survey_code/:response_set_code", :conditions => {:method => :put}, :action => "update" # PUT edited survey
|
10
10
|
end
|
11
11
|
end
|
@@ -29,7 +29,8 @@ class SurveyorGenerator < Rails::Generator::Base
|
|
29
29
|
"create_response_sets", "create_responses",
|
30
30
|
"create_dependencies", "create_dependency_conditions",
|
31
31
|
"create_validations", "create_validation_conditions",
|
32
|
-
"add_display_order_to_surveys", "add_correct_answer_id_to_questions"
|
32
|
+
"add_display_order_to_surveys", "add_correct_answer_id_to_questions",
|
33
|
+
"add_index_to_response_sets", "add_index_to_surveys", "add_unique_indicies"].each_with_index do |model, i|
|
33
34
|
unless (prev_migrations = Dir.glob("db/migrate/[0-9]*_*.rb").grep(/[0-9]+_#{model}.rb$/)).empty?
|
34
35
|
prev_migration_timestamp = prev_migrations[0].match(/([0-9]+)_#{model}.rb$/)[1]
|
35
36
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class AddUniqueIndicies < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
remove_index(:response_sets, :name => 'response_sets_ac_idx')
|
4
|
+
add_index(:response_sets, :access_code, :name => 'response_sets_ac_idx', :unique => true)
|
5
|
+
|
6
|
+
remove_index(:surveys, :name => 'surveys_ac_idx')
|
7
|
+
add_index(:surveys, :access_code, :name => 'surveys_ac_idx', :unique => true)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.down
|
11
|
+
remove_index(:response_sets, :name => 'response_sets_ac_idx')
|
12
|
+
add_index(:response_sets, :access_code, :name => 'response_sets_ac_idx')
|
13
|
+
|
14
|
+
remove_index(:surveys, :name => 'surveys_ac_idx')
|
15
|
+
add_index(:surveys, :access_code, :name => 'surveys_ac_idx')
|
16
|
+
end
|
17
|
+
end
|
data/spec/factories.rb
CHANGED
@@ -2,10 +2,12 @@
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'factory_girl'
|
4
4
|
|
5
|
+
Factory.sequence(:unique_survey_access_code){|n| "simple_survey" << n.to_s }
|
6
|
+
|
5
7
|
Factory.define :survey do |s|
|
6
8
|
s.title {"Simple survey"}
|
7
9
|
s.description {"A simple survey for testing"}
|
8
|
-
s.access_code {
|
10
|
+
s.access_code {Factory.next :unique_survey_access_code}
|
9
11
|
s.active_at {Time.now}
|
10
12
|
s.inactive_at {}
|
11
13
|
s.css_url {}
|
@@ -215,4 +215,31 @@ describe ResponseSet, "with mandatory, dependent questions" do
|
|
215
215
|
@response_set.mandatory_questions_complete?.should be_true
|
216
216
|
@response_set.progress_hash.should == {:questions => 4, :triggered => 4, :triggered_mandatory => 4, :triggered_mandatory_completed => 4}
|
217
217
|
end
|
218
|
+
end
|
219
|
+
describe ResponseSet, "exporting csv" do
|
220
|
+
before(:each) do
|
221
|
+
@section = Factory(:survey_section)
|
222
|
+
# Questions
|
223
|
+
@do_you_like_pie = Factory(:question, :text => "Do you like pie?", :survey_section => @section)
|
224
|
+
@what_flavor = Factory(:question, :text => "What flavor?", :survey_section => @section)
|
225
|
+
@what_bakery = Factory(:question, :text => "What bakery?", :survey_section => @section)
|
226
|
+
# Answers
|
227
|
+
@do_you_like_pie.answers << Factory(:answer, :text => "yes", :question_id => @do_you_like_pie.id)
|
228
|
+
@do_you_like_pie.answers << Factory(:answer, :text => "no", :question_id => @do_you_like_pie.id)
|
229
|
+
@what_flavor.answers << Factory(:answer, :response_class => :string, :question_id => @what_flavor.id)
|
230
|
+
@what_bakery.answers << Factory(:answer, :response_class => :string, :question_id => @what_bakery.id)
|
231
|
+
# Responses
|
232
|
+
@response_set = Factory(:response_set)
|
233
|
+
@response_set.current_section_id = @section.id
|
234
|
+
@response_set.responses << Factory(:response, :question_id => @do_you_like_pie.id, :answer_id => @do_you_like_pie.answers.first.id, :response_set_id => @response_set.id)
|
235
|
+
@response_set.responses << Factory(:response, :string_value => "pecan pie", :question_id => @what_flavor.id, :answer_id => @what_flavor.answers.first.id, :response_set_id => @response_set.id)
|
236
|
+
end
|
237
|
+
it "should export a string with responses" do
|
238
|
+
@response_set.responses.size.should == 2
|
239
|
+
csv = @response_set.to_csv
|
240
|
+
csv.is_a?(String).should be_true
|
241
|
+
csv.should match "question.short_text"
|
242
|
+
csv.should match "What flavor?"
|
243
|
+
csv.should match /pecan pie/
|
244
|
+
end
|
218
245
|
end
|
data/surveyor.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{surveyor}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.11.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Brian Chamberlain", "Mark Yoon"]
|
12
|
-
s.date = %q{2010-04-
|
12
|
+
s.date = %q{2010-04-06}
|
13
13
|
s.email = %q{yoon@northwestern.edu}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"README.md"
|
@@ -111,6 +111,9 @@ Gem::Specification.new do |s|
|
|
111
111
|
"generators/surveyor/templates/initializers/surveyor.rb",
|
112
112
|
"generators/surveyor/templates/migrate/add_correct_answer_id_to_questions.rb",
|
113
113
|
"generators/surveyor/templates/migrate/add_display_order_to_surveys.rb",
|
114
|
+
"generators/surveyor/templates/migrate/add_index_to_response_sets.rb",
|
115
|
+
"generators/surveyor/templates/migrate/add_index_to_surveys.rb",
|
116
|
+
"generators/surveyor/templates/migrate/add_unique_indicies.rb",
|
114
117
|
"generators/surveyor/templates/migrate/create_answers.rb",
|
115
118
|
"generators/surveyor/templates/migrate/create_dependencies.rb",
|
116
119
|
"generators/surveyor/templates/migrate/create_dependency_conditions.rb",
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 11
|
8
8
|
- 0
|
9
|
-
version: 0.
|
9
|
+
version: 0.11.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Brian Chamberlain
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-04-
|
18
|
+
date: 2010-04-06 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -135,6 +135,9 @@ files:
|
|
135
135
|
- generators/surveyor/templates/initializers/surveyor.rb
|
136
136
|
- generators/surveyor/templates/migrate/add_correct_answer_id_to_questions.rb
|
137
137
|
- generators/surveyor/templates/migrate/add_display_order_to_surveys.rb
|
138
|
+
- generators/surveyor/templates/migrate/add_index_to_response_sets.rb
|
139
|
+
- generators/surveyor/templates/migrate/add_index_to_surveys.rb
|
140
|
+
- generators/surveyor/templates/migrate/add_unique_indicies.rb
|
138
141
|
- generators/surveyor/templates/migrate/create_answers.rb
|
139
142
|
- generators/surveyor/templates/migrate/create_dependencies.rb
|
140
143
|
- generators/surveyor/templates/migrate/create_dependency_conditions.rb
|