surveyor 0.19.7 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +22 -0
- data/README.md +1 -1
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/app/helpers/surveyor_helper.rb +5 -1
- data/app/views/partials/_answer.html.haml +4 -4
- data/app/views/partials/_question.html.haml +2 -1
- data/app/views/partials/_question_group.html.haml +7 -2
- data/features/redcap_parser.feature +24 -0
- data/features/step_definitions/surveyor_steps.rb +22 -1
- data/features/support/redcap_new_headers.csv +1 -0
- data/features/support/redcap_whitespace.csv +1 -0
- data/features/surveyor.feature +161 -1
- data/features/surveyor_parser.feature +49 -1
- data/generators/surveyor/surveyor_generator.rb +3 -2
- data/generators/surveyor/templates/assets/javascripts/jquery.surveyor.js +23 -9
- data/generators/surveyor/templates/assets/stylesheets/sass/custom.sass +5 -0
- data/generators/surveyor/templates/assets/stylesheets/sass/surveyor.sass +9 -2
- data/generators/surveyor/templates/migrate/add_display_type_to_answers.rb +13 -0
- data/lib/surveyor/models/answer_methods.rb +2 -2
- data/lib/surveyor/models/dependency_methods.rb +1 -1
- data/lib/surveyor/models/response_methods.rb +1 -1
- data/lib/surveyor/models/response_set_methods.rb +7 -0
- data/lib/surveyor/parser.rb +3 -3
- data/lib/surveyor/redcap_parser.rb +21 -18
- data/lib/surveyor/surveyor_controller_methods.rb +3 -2
- data/lib/surveyor/unparser.rb +1 -1
- data/spec/factories.rb +1 -1
- data/spec/lib/benchmark_spec.rb +22 -0
- data/spec/lib/redcap_parser_spec.rb +22 -0
- data/spec/models/answer_spec.rb +2 -2
- data/spec/models/response_set_spec.rb +20 -0
- data/surveyor.gemspec +8 -3
- metadata +11 -7
- data/.rvmrc +0 -1
data/CHANGELOG
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
0.20.0
|
2
|
+
|
3
|
+
* allow answers to be images. closes #171
|
4
|
+
* moving from answer.hide_label => true to answer.display_type => 'hidden_label'
|
5
|
+
* don't parse redcap formulas. really closes #179
|
6
|
+
* allow more of less whitespace in answer options. closes #179
|
7
|
+
* fixing date, time, and datetime saving via ajax. closes #133
|
8
|
+
* not using separate gemset, using passenger in development
|
9
|
+
* fixed an issue where the last date was sent instead of the currently choosen date for a date field
|
10
|
+
* Save grid responses and ids. Closes #161
|
11
|
+
* dropdowns should save their response ids. closes #180
|
12
|
+
* README should reflect that it is 2011
|
13
|
+
* separate file for custom css and gem upgrade message. closes #151
|
14
|
+
* benchmarking surveyor dump for #166
|
15
|
+
* two-lettered rule keys. this one actually closes #159
|
16
|
+
* two-lettered rule keys. closes #159
|
17
|
+
* fix parsing of question and answer references with q_ and a_ in their names. closes #170
|
18
|
+
* more redcap branching logic. closes #177
|
19
|
+
* dynamically require some columns. closes #178
|
20
|
+
* Fixes problem with updating checkboxes on postgers.
|
21
|
+
* Fix problem when calling Answer.exists?('') under postgers.
|
22
|
+
|
1
23
|
0.19.7
|
2
24
|
|
3
25
|
* fix accidentally allowing through blank pick => any answers
|
data/README.md
CHANGED
@@ -111,4 +111,4 @@ To work on the code fork this github project. Run:
|
|
111
111
|
|
112
112
|
which will generate a test app in testbed. Run rake spec and rake cucumber there, and start writing tests!
|
113
113
|
|
114
|
-
Copyright (c) 2008-
|
114
|
+
Copyright (c) 2008-2011 Brian Chamberlain and Mark Yoon, released under the MIT license
|
data/Rakefile
CHANGED
@@ -15,6 +15,7 @@ begin
|
|
15
15
|
gem.add_dependency 'formtastic'
|
16
16
|
gem.add_dependency 'uuid'
|
17
17
|
gem.add_development_dependency "yard", ">= 0"
|
18
|
+
gem.post_install_message = "Thanks for installing surveyor! The time has come to run the surveyor generator and migrate your database, even if you are upgrading."
|
18
19
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
20
|
end
|
20
21
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.20.0
|
@@ -4,7 +4,7 @@ module SurveyorHelper
|
|
4
4
|
surveyor_stylsheets + surveyor_javascripts
|
5
5
|
end
|
6
6
|
def surveyor_stylsheets
|
7
|
-
stylesheet_link_tag 'surveyor/reset', 'surveyor/dateinput', 'surveyor'
|
7
|
+
stylesheet_link_tag 'surveyor/reset', 'surveyor/dateinput', 'surveyor', 'custom'
|
8
8
|
end
|
9
9
|
def surveyor_javascripts
|
10
10
|
javascript_include_tag 'surveyor/jquery.tools.min', 'surveyor/jquery.surveyor'
|
@@ -50,6 +50,10 @@ module SurveyorHelper
|
|
50
50
|
# end
|
51
51
|
|
52
52
|
# Answers
|
53
|
+
def a_text(obj, pos=nil)
|
54
|
+
return image_tag(obj.text) if obj.is_a?(Answer) and obj.display_type == "image"
|
55
|
+
obj.split_or_hidden_text(pos)
|
56
|
+
end
|
53
57
|
def rc_to_attr(type_sym)
|
54
58
|
case type_sym.to_s
|
55
59
|
when /^date|time$/ then :datetime_value
|
@@ -8,12 +8,12 @@
|
|
8
8
|
= ff.quiet_input :response_group, :value => rg if q.pick != "one" && g && g.display_type == "repeater"
|
9
9
|
- case q.pick
|
10
10
|
- when "one"
|
11
|
-
= ff.input :answer_id, :as => :surveyor_radio, :collection => [[a
|
11
|
+
= ff.input :answer_id, :as => :surveyor_radio, :collection => [[a_text(a), a.id]], :label => false, :input_html => {:class => a.css_class}, :response_class => a.response_class
|
12
12
|
- when "any"
|
13
|
-
= ff.input :answer_id, :as => :surveyor_check_boxes, :collection => [[a
|
13
|
+
= ff.input :answer_id, :as => :surveyor_check_boxes, :collection => [[a_text(a), a.id]], :label => false, :input_html => {:class => a.css_class}, :response_class => a.response_class
|
14
14
|
- when "none"
|
15
15
|
- if %w(date datetime time float integer string text).include? a.response_class
|
16
16
|
= ff.quiet_input :answer_id, :input_html => {:class => a.css_class, :value => a.id}
|
17
|
-
= ff.input rc_to_attr(a.response_class), :as => rc_to_as(a.response_class), :label => a
|
17
|
+
= ff.input rc_to_attr(a.response_class), :as => rc_to_as(a.response_class), :label => a_text(a, :pre).blank? ? false : a_text(a, :pre), :hint => a_text(a, :post), :input_html => generate_pick_none_input_html(r.as(a.response_class), a.default_value, a.css_class)
|
18
18
|
- else
|
19
|
-
= a
|
19
|
+
= a_text(a)
|
@@ -11,7 +11,8 @@
|
|
11
11
|
- f.semantic_fields_for i, r do |ff|
|
12
12
|
= ff.quiet_input :question_id
|
13
13
|
= ff.quiet_input :response_group, :value => rg if g && g.display_type == "repeater"
|
14
|
-
= ff.
|
14
|
+
= ff.quiet_input :id unless r.new_record?
|
15
|
+
= ff.input :answer_id, :as => :select, :collection => q.answers.map{|a| [a.text, a.id]}, :label => q.text
|
15
16
|
- else # :default, :inline, :inline_default
|
16
17
|
- if q.pick == "one"
|
17
18
|
- r = response_for(@response_set, q, nil, rg)
|
@@ -14,12 +14,17 @@
|
|
14
14
|
%tr
|
15
15
|
%th
|
16
16
|
- ten_questions.first.answers.each do |a|
|
17
|
-
%th= a
|
17
|
+
%th= a_text(a)
|
18
18
|
%th
|
19
19
|
- ten_questions.each_with_index do |q, i|
|
20
20
|
%tr{:id => "q_#{q.id}", :class => "q_#{renderer} #{q.css_class(@response_set)}"}
|
21
|
+
- if q.pick == "one"
|
22
|
+
- r = response_for(@response_set, q, nil, g)
|
23
|
+
- i = response_idx # increment the response index since the answer partial skips for q.pick == one
|
24
|
+
- f.semantic_fields_for i, r do |ff|
|
25
|
+
= ff.quiet_input :question_id
|
26
|
+
= ff.quiet_input :id unless r.new_record?
|
21
27
|
%th= q.split_text(:pre)
|
22
|
-
- response_idx if q.pick == "one" # increment the response index since the answer partial skips for q.pick == one
|
23
28
|
- q.answers.each do |a|
|
24
29
|
%td= render a.custom_renderer || '/partials/answer', :g => g, :q => q, :a => a, :f => f
|
25
30
|
%th= q.split_text(:post)
|
@@ -31,3 +31,27 @@ Feature: Survey creation
|
|
31
31
|
And there should be 1 dependencies with:
|
32
32
|
| rule |
|
33
33
|
| A |
|
34
|
+
Scenario: with different headers
|
35
|
+
Given I parse redcap file "redcap_new_headers.csv"
|
36
|
+
Then there should be 1 survey with:
|
37
|
+
||
|
38
|
+
And there should be 1 questions with:
|
39
|
+
||
|
40
|
+
And there should be 2 answers with:
|
41
|
+
||
|
42
|
+
@focus
|
43
|
+
Scenario: with different whitespace
|
44
|
+
Given I parse redcap file "redcap_whitespace.csv"
|
45
|
+
Then there should be 1 survey with:
|
46
|
+
||
|
47
|
+
And there should be 2 questions with:
|
48
|
+
||
|
49
|
+
And there should be 7 answers with:
|
50
|
+
| reference_identifier | text |
|
51
|
+
| 1 | Lexapro |
|
52
|
+
| 2 | Celexa |
|
53
|
+
| 3 | Prozac |
|
54
|
+
| 4 | Paxil |
|
55
|
+
| 5 | Zoloft |
|
56
|
+
| 0 | No |
|
57
|
+
| 1 | Yes |
|
@@ -22,7 +22,7 @@ Then /^there should be (\d+) response set with (\d+) responses? with:$/ do |rs_n
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
Then /^there should be (\d+)
|
25
|
+
Then /^there should be (\d+) dependenc(?:y|ies)$/ do |x|
|
26
26
|
Dependency.count.should == x.to_i
|
27
27
|
end
|
28
28
|
|
@@ -60,3 +60,24 @@ Then /^there should be (\d+) text areas$/ do |count|
|
|
60
60
|
response.should have_selector('textarea', :count => count.to_i)
|
61
61
|
end
|
62
62
|
|
63
|
+
Then /^the question "([^"]*)" should be triggered$/ do |text|
|
64
|
+
response.should have_selector %(fieldset[name="#{text}"][class!="q_hidden"])
|
65
|
+
end
|
66
|
+
|
67
|
+
Then /^there should be (\d+) response with answer "([^"]*)"$/ do |count, answer_text|
|
68
|
+
Response.count.should == count.to_i
|
69
|
+
Response.find_by_answer_id(Answer.find_by_text(answer_text)).should_not be_blank
|
70
|
+
end
|
71
|
+
|
72
|
+
Then /^there should be (\d+) datetime responses with$/ do |count, table|
|
73
|
+
Response.count.should == count.to_i
|
74
|
+
table.hashes.each do |hash|
|
75
|
+
if hash.keys == ["datetime_value"]
|
76
|
+
Response.find_by_datetime_value(DateTime.parse(hash["datetime_value"])).should_not be_blank
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
Then /^I should see the image "([^"]*)"$/ do |src|
|
82
|
+
response.should have_selector %(img[src^="#{src}"])
|
83
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Variable / Field Name,Form Name,Field Units,Section Header,Field Type,Field Label,Choices Calculations OR Slider Labels,Field Note,Text Validation Type OR Show Slider Number,Text Validation Min,Text Validation Max,Identifier?,Branching Logic (Show field only if...),Required Field?
|
@@ -0,0 +1 @@
|
|
1
|
+
Variable / Field Name,Form Name,Field Units,Section Header,Field Type,Field Label,Choices OR Calculations,Field Note,Text Validation Type,Text Validation Min,Text Validation Max,Identifier?,Branching Logic (Show field only if...),Required Field?
|
data/features/surveyor.feature
CHANGED
@@ -168,4 +168,164 @@ Feature: Survey creation
|
|
168
168
|
"""
|
169
169
|
When I start the "Websites" survey
|
170
170
|
Then there should be 3 checkboxes
|
171
|
-
And there should be 3 text areas
|
171
|
+
And there should be 3 text areas
|
172
|
+
|
173
|
+
Scenario: "Double letter rule keys"
|
174
|
+
Given the survey
|
175
|
+
"""
|
176
|
+
survey "Doubles" do
|
177
|
+
section "Two" do
|
178
|
+
q_twin "Are you a twin?", :pick => :one
|
179
|
+
a_yes "Oh yes"
|
180
|
+
a_no "Oh no"
|
181
|
+
|
182
|
+
q_two_first_names "Do you have two first names?", :pick => :one
|
183
|
+
a_yes "Why yes"
|
184
|
+
a_no "Why no"
|
185
|
+
|
186
|
+
q "Do you want to be part of an SNL skit?", :pick => :one
|
187
|
+
a_yes "Um yes"
|
188
|
+
a_no "Um no"
|
189
|
+
dependency :rule => "A or AA"
|
190
|
+
condition_A :q_twin, "==", :a_yes
|
191
|
+
condition_AA :q_two_first_names, "==", :a_yes
|
192
|
+
end
|
193
|
+
section "Deux" do
|
194
|
+
label "Here for the ride"
|
195
|
+
end
|
196
|
+
section "Three" do
|
197
|
+
label "Here for the ride"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
"""
|
201
|
+
When I start the "Doubles" survey
|
202
|
+
Then I choose "Oh yes"
|
203
|
+
And I press "Deux"
|
204
|
+
And I press "Two"
|
205
|
+
Then the question "Do you want to be part of an SNL skit?" should be triggered
|
206
|
+
|
207
|
+
Scenario: "Changing dropdowns"
|
208
|
+
Given the survey
|
209
|
+
"""
|
210
|
+
survey "Drop" do
|
211
|
+
section "Like it is hot" do
|
212
|
+
q "Name", :pick => :one, :display_type => :dropdown
|
213
|
+
a "Snoop"
|
214
|
+
a "Dogg"
|
215
|
+
a "D-O double G"
|
216
|
+
a "S-N double O-P, D-O double G"
|
217
|
+
end
|
218
|
+
section "Two" do
|
219
|
+
label "Here for the ride"
|
220
|
+
end
|
221
|
+
section "Three" do
|
222
|
+
label "Here for the ride"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
"""
|
226
|
+
When I start the "Drop" survey
|
227
|
+
Then I select "Snoop" from "Name"
|
228
|
+
And I press "Two"
|
229
|
+
And I press "Like it is hot"
|
230
|
+
And I select "Dogg" from "Name"
|
231
|
+
And I press "Two"
|
232
|
+
Then there should be 1 response with answer "Dogg"
|
233
|
+
|
234
|
+
Scenario: "Saving grids"
|
235
|
+
Given the survey
|
236
|
+
"""
|
237
|
+
survey "Grid" do
|
238
|
+
section "One" do
|
239
|
+
grid "Tell us how often do you cover these each day" do
|
240
|
+
a "1"
|
241
|
+
a "2"
|
242
|
+
a "3"
|
243
|
+
q "Head", :pick => :one
|
244
|
+
q "Knees", :pick => :one
|
245
|
+
q "Toes", :pick => :one
|
246
|
+
end
|
247
|
+
end
|
248
|
+
section "Two" do
|
249
|
+
label "Here for the ride"
|
250
|
+
end
|
251
|
+
section "Three" do
|
252
|
+
label "Here for the ride"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
"""
|
256
|
+
When I start the "Grid" survey
|
257
|
+
Then I choose "1"
|
258
|
+
And I press "Two"
|
259
|
+
And I press "One"
|
260
|
+
Then there should be 1 response with answer "1"
|
261
|
+
|
262
|
+
Scenario: "Dates"
|
263
|
+
Given the survey
|
264
|
+
"""
|
265
|
+
survey "When" do
|
266
|
+
section "One" do
|
267
|
+
q "Tell us when you want to meet"
|
268
|
+
a "Give me a date", :date
|
269
|
+
end
|
270
|
+
section "Two" do
|
271
|
+
q "Tell us when you'd like to eat"
|
272
|
+
a :time
|
273
|
+
end
|
274
|
+
section "Three" do
|
275
|
+
q "Tell us when you'd like a phone call"
|
276
|
+
a :datetime
|
277
|
+
end
|
278
|
+
end
|
279
|
+
"""
|
280
|
+
When I start the "When" survey
|
281
|
+
# 2/14/11
|
282
|
+
And I fill in "Give me a date" with "2011-02-14"
|
283
|
+
# 1:30am
|
284
|
+
And I press "Two"
|
285
|
+
And I select "01" from "Hour"
|
286
|
+
And I select "30" from "Minute"
|
287
|
+
# 2/15/11 5:30pm
|
288
|
+
And I press "Three"
|
289
|
+
And I select "2011" from "Year"
|
290
|
+
And I select "February" from "Month"
|
291
|
+
And I select "15" from "Day"
|
292
|
+
And I select "17" from "Hour"
|
293
|
+
And I select "30" from "Minute"
|
294
|
+
And I press "One"
|
295
|
+
|
296
|
+
Then there should be 3 datetime responses with
|
297
|
+
| datetime_value |
|
298
|
+
| 2011-02-14 00:00:00 |
|
299
|
+
| 2001-01-01 01:30:00 |
|
300
|
+
| 2011-02-15 17:30:00 |
|
301
|
+
|
302
|
+
# 2/13/11
|
303
|
+
And I fill in "Give me a date" with "2011-02-13"
|
304
|
+
# 1:30pm
|
305
|
+
And I press "Two"
|
306
|
+
And I select "13" from "Hour"
|
307
|
+
# 2/15/11 5:00pm
|
308
|
+
And I press "Three"
|
309
|
+
And I select "00" from "Minute"
|
310
|
+
And I press "Click here to finish"
|
311
|
+
|
312
|
+
Then there should be 3 datetime responses with
|
313
|
+
| datetime_value |
|
314
|
+
| 2011-02-13 00:00:00 |
|
315
|
+
| 2001-01-01 13:30:00 |
|
316
|
+
| 2011-02-15 17:00:00 |
|
317
|
+
|
318
|
+
Scenario: "Images"
|
319
|
+
Given the survey
|
320
|
+
"""
|
321
|
+
survey "Images" do
|
322
|
+
section "One" do
|
323
|
+
q "Which way?"
|
324
|
+
a "/images/surveyor/next.gif", :display_type => "image"
|
325
|
+
a "/images/surveyor/prev.gif", :display_type => "image"
|
326
|
+
end
|
327
|
+
end
|
328
|
+
"""
|
329
|
+
When I start the "Images" survey
|
330
|
+
Then I should see the image "/images/surveyor/next.gif"
|
331
|
+
And I should see the image "/images/surveyor/prev.gif"
|
@@ -238,4 +238,52 @@ Feature: Survey creation
|
|
238
238
|
"""
|
239
239
|
Then there should be 4 dependencies
|
240
240
|
And 2 dependencies should depend on questions
|
241
|
-
And 2 dependencies should depend on question groups
|
241
|
+
And 2 dependencies should depend on question groups
|
242
|
+
|
243
|
+
Scenario: Dependencies with "a"
|
244
|
+
Given the survey
|
245
|
+
"""
|
246
|
+
survey "Dependencies with 'a'" do
|
247
|
+
section "First" do
|
248
|
+
q_data_collection "Disease data collection", :pick => :one
|
249
|
+
a_via_chart_review "Via chart review"
|
250
|
+
a_via_patient_interview "Via patient interview/questionnaire"
|
251
|
+
|
252
|
+
q_myocardial_infaction "Myocardinal Infarction", :pick => :one
|
253
|
+
dependency :rule => "A"
|
254
|
+
condition_A :q_data_collection, "==", :a_via_chart_review
|
255
|
+
a_yes "Yes"
|
256
|
+
a_no "No"
|
257
|
+
end
|
258
|
+
end
|
259
|
+
"""
|
260
|
+
And there should be 1 dependency with:
|
261
|
+
| rule |
|
262
|
+
| A |
|
263
|
+
And there should be 1 resolved dependency_condition with:
|
264
|
+
| rule_key |
|
265
|
+
| A |
|
266
|
+
|
267
|
+
Scenario: Dependencies with "q"
|
268
|
+
Given the survey
|
269
|
+
"""
|
270
|
+
survey "Dependencies with 'q'" do
|
271
|
+
section "First" do
|
272
|
+
q_rawq_collection "Your rockin rawq collection", :pick => :one
|
273
|
+
a_rawqs "Rawqs"
|
274
|
+
a_doesnt_rawq "Doesn't rawq"
|
275
|
+
|
276
|
+
q_do_you_rawq "Do you rawq with your rockin rawq collection?", :pick => :one
|
277
|
+
dependency :rule => "A"
|
278
|
+
condition_A :q_rawq_collection, "==", :a_rawqs
|
279
|
+
a_yes "Yes"
|
280
|
+
a_no "No"
|
281
|
+
end
|
282
|
+
end
|
283
|
+
"""
|
284
|
+
And there should be 1 dependency with:
|
285
|
+
| rule |
|
286
|
+
| A |
|
287
|
+
And there should be 1 resolved dependency_condition with:
|
288
|
+
| rule_key |
|
289
|
+
| A |
|
@@ -28,7 +28,8 @@ class SurveyorGenerator < Rails::Generator::Base
|
|
28
28
|
"add_display_order_to_surveys", "add_correct_answer_id_to_questions",
|
29
29
|
"add_index_to_response_sets", "add_index_to_surveys",
|
30
30
|
"add_unique_indicies", "add_section_id_to_responses",
|
31
|
-
"add_default_value_to_answers", "add_api_ids"
|
31
|
+
"add_default_value_to_answers", "add_api_ids",
|
32
|
+
"add_display_type_to_answers"].each_with_index do |model, i|
|
32
33
|
unless (prev_migrations = Dir.glob("db/migrate/[0-9]*_*.rb").grep(/[0-9]+_#{model}.rb$/)).empty?
|
33
34
|
prev_migration_timestamp = prev_migrations[0].match(/([0-9]+)_#{model}.rb$/)[1]
|
34
35
|
end
|
@@ -45,7 +46,7 @@ class SurveyorGenerator < Rails::Generator::Base
|
|
45
46
|
end
|
46
47
|
m.directory "public/stylesheets/sass"
|
47
48
|
m.file "assets/stylesheets/sass/surveyor.sass", "public/stylesheets/sass/surveyor.sass"
|
48
|
-
|
49
|
+
m.file "assets/stylesheets/sass/custom.sass", "public/stylesheets/sass/custom.sass"
|
49
50
|
|
50
51
|
# Locales
|
51
52
|
m.directory "config/locales"
|
@@ -2,25 +2,37 @@
|
|
2
2
|
jQuery(document).ready(function(){
|
3
3
|
// if(jQuery.browser.msie){
|
4
4
|
// // IE has trouble with the change event for form radio/checkbox elements - bind click instead
|
5
|
-
// jQuery("form#survey_form input[type=radio], form#survey_form [type=checkbox]").bind("click", function(){
|
5
|
+
// jQuery("form#survey_form input[type=radio], form#survey_form [type=checkbox]").bind("click", function(){
|
6
6
|
// jQuery(this).parents("form").ajaxSubmit({dataType: 'json', success: successfulSave});
|
7
7
|
// });
|
8
8
|
// // IE fires the change event for all other (not radio/checkbox) elements of the form
|
9
|
-
// jQuery("form#survey_form *").not("input[type=radio], input[type=checkbox]").bind("change", function(){
|
10
|
-
// jQuery(this).parents("form").ajaxSubmit({dataType: 'json', success: successfulSave});
|
9
|
+
// jQuery("form#survey_form *").not("input[type=radio], input[type=checkbox]").bind("change", function(){
|
10
|
+
// jQuery(this).parents("form").ajaxSubmit({dataType: 'json', success: successfulSave});
|
11
11
|
// });
|
12
12
|
// }else{
|
13
13
|
// // Other browsers just use the change event on the form
|
14
|
+
|
15
|
+
// For a date input, i.e. using dateinput from jQuery tools, the value is not updated
|
16
|
+
// before the onChange or change event is fired, so we hang this in before the update is
|
17
|
+
// sent to the server and set the correct value from the dateinput object.
|
18
|
+
jQuery('li.date input').change(function(){
|
19
|
+
if ( $(this).data('dateinput') ) {
|
20
|
+
var date_obj = $(this).data('dateinput').getValue();
|
21
|
+
this.value = date_obj.getFullYear() + "-" + (date_obj.getMonth()+1) + "-" +
|
22
|
+
date_obj.getDate() + " 00:00:00 UTC";
|
23
|
+
}
|
24
|
+
});
|
25
|
+
|
14
26
|
jQuery("form#survey_form input, form#survey_form select, form#survey_form textarea").change(function(){
|
15
|
-
question_data = $(this).parents('fieldset[id^="q_"]').find("input, select, textarea").add($("form#survey_form input[name='authenticity_token']")).serialize();
|
27
|
+
question_data = $(this).parents('fieldset[id^="q_"],tr[id^="q_"]').find("input, select, textarea").add($("form#survey_form input[name='authenticity_token']")).serialize();
|
16
28
|
// console.log(unescape(question_data));
|
17
29
|
$.ajax({ type: "PUT", url: $(this).parents('form#survey_form').attr("action"), data: question_data, dataType: 'json', success: successfulSave })
|
18
30
|
});
|
19
31
|
// }
|
20
|
-
|
32
|
+
|
21
33
|
// If javascript works, we don't need to show dependents from previous sections at the top of the page.
|
22
34
|
jQuery("#dependents").remove();
|
23
|
-
|
35
|
+
|
24
36
|
function successfulSave(responseText){ // for(key in responseText) { console.log("key is "+[key]+", value is "+responseText[key]); }
|
25
37
|
// surveyor_controller returns a json object to show/hide elements and insert/remove ids e.g. {"ids": {"2" => 234}, "remove": {"4" => 21}, "hide":["question_12","question_13"],"show":["question_14"]}
|
26
38
|
jQuery.each(responseText.show, function(){ jQuery('#' + this).show("fast"); });
|
@@ -29,7 +41,7 @@ jQuery(document).ready(function(){
|
|
29
41
|
jQuery.each(responseText.remove, function(k,v){ jQuery('#r_'+k+'_id[value="'+v+'"]').remove(); });
|
30
42
|
return false;
|
31
43
|
}
|
32
|
-
|
44
|
+
|
33
45
|
// is_exclusive checkboxes should disble sibling checkboxes
|
34
46
|
$('input.exclusive:checked').parents('fieldset[id^="q_"]').find(':checkbox').not(".exclusive").attr('checked', false).attr('disabled', true);
|
35
47
|
$('input.exclusive:checkbox').click(function(){
|
@@ -41,6 +53,8 @@ jQuery(document).ready(function(){
|
|
41
53
|
others.attr('disabled', false);
|
42
54
|
}
|
43
55
|
});
|
44
|
-
|
45
|
-
$('li.date input').dateinput(
|
56
|
+
|
57
|
+
$('li.date input').dateinput({
|
58
|
+
format: 'dd mmm yyyy'
|
59
|
+
});
|
46
60
|
});
|
@@ -1,3 +1,9 @@
|
|
1
|
+
/* Do not change surveyor.sass or the generated
|
2
|
+
* surveyor.css. They will be overwritten by
|
3
|
+
* the surveyor generator. Instead, add
|
4
|
+
* custom styles to custom.sass, which will be
|
5
|
+
* loaded after the surveyor stylesheets */
|
6
|
+
|
1
7
|
$background_color:#EEEEEE
|
2
8
|
$surveyor_flash_background_color:#FFF1A8
|
3
9
|
$surveyor_color:#FFFFF1
|
@@ -103,8 +109,9 @@ body
|
|
103
109
|
legend
|
104
110
|
:background-color $surveyor_dependent_color
|
105
111
|
:padding 3px 3px 3px 0
|
106
|
-
|
107
|
-
|
112
|
+
fieldset.q_dropdown, fieldset.q_inline_dropdown, fieldset.q_slider, fieldset.q_repeater_dropdown
|
113
|
+
label
|
114
|
+
:display none
|
108
115
|
|
109
116
|
// buttons
|
110
117
|
input[type="submit"]
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class AddDisplayTypeToAnswers < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :answers, :display_type, :string
|
4
|
+
Answer.all.each{|a| a.update_attributes(:display_type => "hidden_label") if a.hide_label == true}
|
5
|
+
remove_column :answers, :hide_label
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.down
|
9
|
+
add_column :answers, :hide_label, :boolean
|
10
|
+
Answer.all.each{|a| a.update_attributes(:hide_label => true) if a.display_type == "hidden_label"}
|
11
|
+
remove_column :answers, :display_type
|
12
|
+
end
|
13
|
+
end
|
@@ -31,7 +31,7 @@ module Surveyor
|
|
31
31
|
def default_args
|
32
32
|
self.display_order ||= self.question ? self.question.answers.count : 0
|
33
33
|
self.is_exclusive ||= false
|
34
|
-
self.
|
34
|
+
self.display_type ||= "default"
|
35
35
|
self.response_class ||= "answer"
|
36
36
|
self.short_text ||= text
|
37
37
|
self.data_export_identifier ||= Surveyor::Common.normalize(text)
|
@@ -43,7 +43,7 @@ module Surveyor
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def split_or_hidden_text(part = nil)
|
46
|
-
return "" if
|
46
|
+
return "" if display_type == "hidden_label"
|
47
47
|
part == :pre ? text.split("|",2)[0] : (part == :post ? text.split("|",2)[1] : text)
|
48
48
|
end
|
49
49
|
|
@@ -42,7 +42,7 @@ module Surveyor
|
|
42
42
|
# logger.debug "rexp: #{rgx.inspect}"
|
43
43
|
# logger.debug "keyp: #{ch.inspect}"
|
44
44
|
# logger.debug "subd: #{self.rule.gsub(rgx){|m| ch[m.to_sym]}}"
|
45
|
-
rgx = Regexp.new(self.dependency_conditions.map{|dc| ["a","o"].include?(dc.rule_key) ? "#{dc.rule_key}(?!nd|r)" : dc.rule_key}.join("|")) # exclude and, or
|
45
|
+
rgx = Regexp.new(self.dependency_conditions.map{|dc| ["a","o"].include?(dc.rule_key) ? "\\b#{dc.rule_key}(?!nd|r)\\b" : "\\b#{dc.rule_key}\\b"}.join("|")) # exclude and, or
|
46
46
|
eval(self.rule.gsub(rgx){|m| ch[m.to_sym]})
|
47
47
|
end
|
48
48
|
|
@@ -20,7 +20,7 @@ module Surveyor
|
|
20
20
|
def applicable_attributes(attrs)
|
21
21
|
result = HashWithIndifferentAccess.new(attrs)
|
22
22
|
answer_id = result[:answer_id].is_a?(Array) ? result[:answer_id].last : result[:answer_id] # checkboxes are arrays / radio buttons are not arrays
|
23
|
-
if result[:string_value] && Answer.exists?(answer_id)
|
23
|
+
if result[:string_value] && !answer_id.blank? && Answer.exists?(answer_id)
|
24
24
|
answer = Answer.find(answer_id)
|
25
25
|
result.delete(:string_value) unless answer.response_class && answer.response_class.to_sym == :string
|
26
26
|
end
|
@@ -42,6 +42,13 @@ module Surveyor
|
|
42
42
|
return false if (q = Question.find_by_id(hash["question_id"])) and q.pick == "one"
|
43
43
|
hash.any?{|k,v| v.is_a?(Array) ? v.all?{|x| x.to_s.blank?} : v.to_s.blank?}
|
44
44
|
end
|
45
|
+
def trim_for_lookups(hash_of_hashes)
|
46
|
+
result = {}
|
47
|
+
(reject_or_destroy_blanks(hash_of_hashes) || {}).each_pair do |k, hash|
|
48
|
+
result.merge!({k => {"question_id" => hash["question_id"], "answer_id" => hash["answer_id"]}.merge(hash.has_key?("response_group") ? {"response_group" => hash["response_group"]} : {} ).merge(hash.has_key?("id") ? {"id" => hash["id"]} : {} ).merge(hash.has_key?("_destroy") ? {"_destroy" => hash["_destroy"]} : {} )})
|
49
|
+
end
|
50
|
+
result
|
51
|
+
end
|
45
52
|
end
|
46
53
|
end
|
47
54
|
|
data/lib/surveyor/parser.rb
CHANGED
@@ -192,11 +192,11 @@ class DependencyCondition < ActiveRecord::Base
|
|
192
192
|
{
|
193
193
|
:context_reference => context,
|
194
194
|
:operator => a1 || "==",
|
195
|
-
:question_reference => a0.to_s.gsub(
|
195
|
+
:question_reference => a0.to_s.gsub(/^q_/, ""),
|
196
196
|
:rule_key => reference_identifier
|
197
197
|
}.merge(
|
198
198
|
a2.is_a?(Hash) ? a2 : { :answer_reference =>
|
199
|
-
a2.to_s.gsub(
|
199
|
+
a2.to_s.gsub(/^a_/, "") }
|
200
200
|
)
|
201
201
|
)
|
202
202
|
end
|
@@ -258,7 +258,7 @@ class Answer < ActiveRecord::Base
|
|
258
258
|
when :none, :omit # is_exclusive erases and disables other checkboxes and input elements
|
259
259
|
self.text_args(arg.to_s.humanize).merge({:is_exclusive => true})
|
260
260
|
when :integer, :date, :time, :datetime, :text, :datetime, :string
|
261
|
-
self.text_args(arg.to_s.humanize).merge({:response_class => arg.to_s, :
|
261
|
+
self.text_args(arg.to_s.humanize).merge({:response_class => arg.to_s, :display_type => "hidden_label"})
|
262
262
|
end
|
263
263
|
end
|
264
264
|
end
|
@@ -24,7 +24,7 @@ module Surveyor
|
|
24
24
|
begin
|
25
25
|
csvlib.parse(str, :headers => :first_row, :return_headers => true, :header_converters => :symbol) do |r|
|
26
26
|
if r.header_row? # header row
|
27
|
-
return puts "Missing headers: #{missing_columns(r).inspect}\n\n" unless missing_columns(r).blank?
|
27
|
+
return puts "Missing headers: #{missing_columns(r.headers).inspect}\n\n" unless missing_columns(r.headers).blank?
|
28
28
|
context[:survey] = Survey.new(:title => filename)
|
29
29
|
print "survey_#{context[:survey].access_code} "
|
30
30
|
else # non-header rows
|
@@ -44,10 +44,14 @@ module Surveyor
|
|
44
44
|
return context[:survey]
|
45
45
|
end
|
46
46
|
def missing_columns(r)
|
47
|
-
|
47
|
+
missing = []
|
48
|
+
missing << "choices_or_calculations" unless r.map(&:to_s).include?("choices_or_calculations") or r.map(&:to_s).include?("choices_calculations_or_slider_labels")
|
49
|
+
missing << "text_validation_type" unless r.map(&:to_s).include?("text_validation_type") or r.map(&:to_s).include?("text_validation_type_or_show_slider_number")
|
50
|
+
missing += (static_required_columns - r.map(&:to_s))
|
48
51
|
end
|
49
|
-
def
|
50
|
-
|
52
|
+
def static_required_columns
|
53
|
+
# no longer requiring field_units
|
54
|
+
%w(variable__field_name form_name section_header field_type field_label field_note text_validation_min text_validation_max identifier branching_logic_show_field_only_if required_field)
|
51
55
|
end
|
52
56
|
end
|
53
57
|
end
|
@@ -110,19 +114,18 @@ class Dependency < ActiveRecord::Base
|
|
110
114
|
end
|
111
115
|
end
|
112
116
|
def self.decompose_component(str)
|
113
|
-
|
114
|
-
if match = str.match(/^\[(\w+)\] ?([!=><]+) ?"(
|
115
|
-
{:question_reference => match[1], :operator => match[2].gsub(/^=$/, "=="), :answer_reference => match[3]}
|
116
|
-
# [initial_119(2)] = "1"
|
117
|
-
elsif match = str.match(/^\[(\w+)\((\w+)\)\] ?([!=><]+) ?"1"$/)
|
118
|
-
{:question_reference => match[1], :operator => match[3].gsub(/^=$/, "=="), :answer_reference => match[2]}
|
119
|
-
# [f1_q15] >= 21
|
120
|
-
elsif match = str.match(/^\[(\w+)\] ?([!=><]+) ?(
|
121
|
-
{:question_reference => match[1], :operator => match[2].gsub(/^=$/, "=="), :integer_value => match[3]}
|
122
|
-
# uhoh
|
117
|
+
# [initial_52] = "1" or [f1_q15] = '' or [f1_q15] = '-2' or [hi_event1_type] <> ''
|
118
|
+
if match = str.match(/^\[(\w+)\] ?([!=><]+) ?['"](-?\w*)['"]$/)
|
119
|
+
{:question_reference => match[1], :operator => match[2].gsub(/^=$/, "==").gsub(/^<>$/, "!="), :answer_reference => match[3]}
|
120
|
+
# [initial_119(2)] = "1" or [hiprep_heat2(97)] = '1'
|
121
|
+
elsif match = str.match(/^\[(\w+)\((\w+)\)\] ?([!=><]+) ?['"]1['"]$/)
|
122
|
+
{:question_reference => match[1], :operator => match[3].gsub(/^=$/, "==").gsub(/^<>$/, "!="), :answer_reference => match[2]}
|
123
|
+
# [f1_q15] >= 21 or [f1_q15] >= -21
|
124
|
+
elsif match = str.match(/^\[(\w+)\] ?([!=><]+) ?(-?\d+)$/)
|
125
|
+
{:question_reference => match[1], :operator => match[2].gsub(/^=$/, "==").gsub(/^<>$/, "!="), :integer_value => match[3]}
|
123
126
|
else
|
124
127
|
puts "\n!!! skipping dependency_condition #{str}"
|
125
|
-
end
|
128
|
+
end
|
126
129
|
end
|
127
130
|
def self.decompose_rule(str)
|
128
131
|
# see spec/lib/redcap_parser_spec.rb for examples
|
@@ -181,9 +184,9 @@ class Answer < ActiveRecord::Base
|
|
181
184
|
when "file"
|
182
185
|
puts "\n!!! skipping answer: file"
|
183
186
|
end
|
184
|
-
r[:choices_or_calculations].to_s.split("|").each do |pair|
|
185
|
-
aref, atext = pair.
|
186
|
-
if aref.blank? or atext.blank?
|
187
|
+
(r[:choices_or_calculations] || r[:choices_calculations_or_slider_labels]).to_s.split("|").each do |pair|
|
188
|
+
aref, atext = pair.split(",").map(&:strip)
|
189
|
+
if aref.blank? or atext.blank? or (aref.to_i.to_s != aref)
|
187
190
|
puts "\n!!! skipping answer #{pair}"
|
188
191
|
else
|
189
192
|
context[:answer] = context[:question].answers.build(:reference_identifier => aref, :text => atext)
|
@@ -75,8 +75,9 @@ module Surveyor
|
|
75
75
|
end
|
76
76
|
format.js do
|
77
77
|
ids, remove, question_ids = {}, {}, []
|
78
|
-
ResponseSet.
|
79
|
-
|
78
|
+
ResponseSet.trim_for_lookups(params[:r]).each do |k,v|
|
79
|
+
v[:answer_id].reject!(&:blank?) if v[:answer_id].is_a?(Array)
|
80
|
+
ids[k] = @response_set.responses.find(:first, :conditions => v, :order => "created_at DESC").id if !v.has_key?("id")
|
80
81
|
remove[k] = v["id"] if v.has_key?("id") && v.has_key?("_destroy")
|
81
82
|
question_ids << v["question_id"]
|
82
83
|
end
|
data/lib/surveyor/unparser.rb
CHANGED
@@ -111,7 +111,7 @@ class Answer < ActiveRecord::Base
|
|
111
111
|
dsl << " " if question.part_of_group?
|
112
112
|
dsl << " a"
|
113
113
|
dsl << "_#{reference_identifier}" unless reference_identifier.blank?
|
114
|
-
if response_class.to_s.titlecase == text && attrs == {:
|
114
|
+
if response_class.to_s.titlecase == text && attrs == {:display_type => "hidden_label"}
|
115
115
|
dsl << " :#{response_class}"
|
116
116
|
else
|
117
117
|
dsl << [ text.blank? ? nil : text == "Other" ? " :other" : text == "Omit" ? " :omit" : " \"#{text}\"",
|
data/spec/factories.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Surveyor do
|
4
|
+
it "should write thousands of response sets" do
|
5
|
+
Surveyor::Parser.parse(File.read(File.join(Rails.root, 'surveys', 'kitchen_sink_survey.rb')))
|
6
|
+
survey = Survey.last
|
7
|
+
rs = ResponseSet.create(:survey => survey)
|
8
|
+
survey.sections.each{|s| s.questions.each{|q| rs.responses.create(:question => q, :answer => q.answers.first)}}
|
9
|
+
Benchmark.bm 20 do |x|
|
10
|
+
x.report "a test" do
|
11
|
+
full_path = File.join(Rails.root,"#{survey.access_code}_#{Time.now.to_i}.csv")
|
12
|
+
File.open(full_path, 'w') do |f|
|
13
|
+
100.times do # adjust this to test
|
14
|
+
survey.response_sets.each_with_index{|r,i| f.write(r.to_csv(true, i == 0)) } # print access code every time, print_header first time
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
@@ -4,6 +4,20 @@ describe Surveyor::RedcapParser do
|
|
4
4
|
before(:each) do
|
5
5
|
# @parser = Surveyor::Parser.new
|
6
6
|
end
|
7
|
+
it "should require specific columns" do
|
8
|
+
# with standard fields
|
9
|
+
x = %w(field_units choices_or_calculations text_validation_type variable__field_name form_name section_header field_type field_label field_note text_validation_min text_validation_max identifier branching_logic_show_field_only_if required_field)
|
10
|
+
Surveyor::RedcapParser.new.missing_columns(x).should be_blank
|
11
|
+
# without field_units
|
12
|
+
y = %w(choices_or_calculations text_validation_type variable__field_name form_name section_header field_type field_label field_note text_validation_min text_validation_max identifier branching_logic_show_field_only_if required_field)
|
13
|
+
Surveyor::RedcapParser.new.missing_columns(y).should be_blank
|
14
|
+
# choices_or_calculations => choices_calculations_or_slider_labels
|
15
|
+
z = %w(field_units choices_calculations_or_slider_labels text_validation_type variable__field_name form_name section_header field_type field_label field_note text_validation_min text_validation_max identifier branching_logic_show_field_only_if required_field)
|
16
|
+
Surveyor::RedcapParser.new.missing_columns(z).should be_blank
|
17
|
+
# text_validation_type => text_validation_type_or_show_slider_number
|
18
|
+
a = %w(field_units choices_or_calculations text_validation_type_or_show_slider_number variable__field_name form_name section_header field_type field_label field_note text_validation_min text_validation_max identifier branching_logic_show_field_only_if required_field)
|
19
|
+
Surveyor::RedcapParser.new.missing_columns(a).should be_blank
|
20
|
+
end
|
7
21
|
it "should decompose dependency rules" do
|
8
22
|
# basic
|
9
23
|
Dependency.decompose_rule('[f1_q12]="1"').should == {:rule => "A", :components => ['[f1_q12]="1"']}
|
@@ -44,6 +58,14 @@ describe Surveyor::RedcapParser do
|
|
44
58
|
Dependency.decompose_component('[initial_52] = "1"').should == {:question_reference => 'initial_52', :operator => '==', :answer_reference => '1'}
|
45
59
|
Dependency.decompose_component('[initial_119(2)] = "1"').should == {:question_reference => 'initial_119', :operator => '==', :answer_reference => '2'}
|
46
60
|
Dependency.decompose_component('[f1_q15] >= 21').should == {:question_reference => 'f1_q15', :operator => '>=', :integer_value => '21'}
|
61
|
+
# basic, blanks
|
62
|
+
Dependency.decompose_component("[f1_q15]=''").should == {:question_reference => 'f1_q15', :operator => '==', :answer_reference => ''}
|
63
|
+
# basic, negatives
|
64
|
+
Dependency.decompose_component("[f1_q15]='-2'").should == {:question_reference => 'f1_q15', :operator => '==', :answer_reference => '-2'}
|
65
|
+
# internal parenthesis
|
66
|
+
Dependency.decompose_component("[hiprep_heat2(97)] = '1'").should == {:question_reference => 'hiprep_heat2', :operator => '==', :answer_reference => '97'}
|
67
|
+
Dependency.decompose_component("[hi_event1_type] <> ''").should == {:question_reference => 'hi_event1_type', :operator => '!=', :answer_reference => ''}
|
68
|
+
|
47
69
|
end
|
48
70
|
it "should return a survey object" do
|
49
71
|
x = %("Variable / Field Name","Form Name","Field Units","Section Header","Field Type","Field Label","Choices OR Calculations","Field Note","Text Validation Type","Text Validation Min","Text Validation Max",Identifier?,"Branching Logic (Show field only if...)","Required Field?"\nstudy_id,demographics,,,text,"Study ID",,,,,,,,)
|
data/spec/models/answer_spec.rb
CHANGED
@@ -22,9 +22,9 @@ describe Answer, "when creating a new answer" do
|
|
22
22
|
@answer.css_class.should == "exclusive foo bar"
|
23
23
|
end
|
24
24
|
|
25
|
-
it "should hide the label when
|
25
|
+
it "should hide the label when display_type hidden_label is set" do
|
26
26
|
@answer.split_or_hidden_text.should == "Red"
|
27
|
-
@answer.
|
27
|
+
@answer.display_type = "hidden_label"
|
28
28
|
@answer.split_or_hidden_text.should == ""
|
29
29
|
end
|
30
30
|
it "should split up pre/post labels" do
|
@@ -125,6 +125,26 @@ describe ResponseSet do
|
|
125
125
|
"32" => {"question_id" => @qone.id, "answer_id" => "291", "string_value" => ""} # new radio with blank string value, selected
|
126
126
|
}
|
127
127
|
end
|
128
|
+
it "should clean up responses for lookups to get ids after saving via ajax" do
|
129
|
+
hash_of_hashes = {"1"=>{"question_id"=>"2", "answer_id"=>"1"},
|
130
|
+
"2"=>{"question_id"=>"3", "answer_id"=>["", "6"]},
|
131
|
+
"9"=>{"question_id"=>"6", "string_value"=>"jack", "answer_id"=>"13"},
|
132
|
+
"17"=>{"question_id"=>"13", "datetime_value(1i)"=>"2006", "datetime_value(2i)"=>"2", "datetime_value(3i)"=>"4", "datetime_value(4i)"=>"02", "datetime_value(5i)"=>"05", "answer_id"=>"21"},
|
133
|
+
"18"=>{"question_id"=>"14", "datetime_value(1i)"=>"1", "datetime_value(2i)"=>"1", "datetime_value(3i)"=>"1", "datetime_value(4i)"=>"01", "datetime_value(5i)"=>"02", "answer_id"=>"22"},
|
134
|
+
"19"=>{"question_id"=>"15", "datetime_value"=>"", "answer_id"=>"23", "id" => "1"},
|
135
|
+
"47"=>{"question_id"=>"38", "answer_id"=>"220", "integer_value"=>"2", "id" => "2"},
|
136
|
+
"61"=>{"question_id"=>"44", "response_group"=>"0", "answer_id"=>"241", "integer_value"=>"12"}}
|
137
|
+
ResponseSet.trim_for_lookups(hash_of_hashes).should ==
|
138
|
+
{ "1"=>{"question_id"=>"2", "answer_id"=>"1"},
|
139
|
+
"2"=>{"question_id"=>"3", "answer_id"=>["", "6"]},
|
140
|
+
"9"=>{"question_id"=>"6", "answer_id"=>"13"},
|
141
|
+
"17"=>{"question_id"=>"13", "answer_id"=>"21"},
|
142
|
+
"18"=>{"question_id"=>"14", "answer_id"=>"22"},
|
143
|
+
"19"=>{"question_id"=>"15", "answer_id"=>"23", "id" => "1", "_destroy" => "true"},
|
144
|
+
"47"=>{"question_id"=>"38", "answer_id"=>"220", "id" => "2"},
|
145
|
+
"61"=>{"question_id"=>"44", "response_group"=>"0", "answer_id"=>"241"}
|
146
|
+
}
|
147
|
+
end
|
128
148
|
it "should remove responses" do
|
129
149
|
r = @response_set.responses.create(:question_id => 1, :answer_id => 2)
|
130
150
|
r.id.should_not be nil
|
data/surveyor.gemspec
CHANGED
@@ -5,17 +5,16 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{surveyor}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.20.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{2011-
|
12
|
+
s.date = %q{2011-07-11}
|
13
13
|
s.email = %q{yoon@northwestern.edu}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"README.md"
|
16
16
|
]
|
17
17
|
s.files = [
|
18
|
-
".rvmrc",
|
19
18
|
"CHANGELOG",
|
20
19
|
"MIT-LICENSE",
|
21
20
|
"README.md",
|
@@ -61,7 +60,9 @@ Gem::Specification.new do |s|
|
|
61
60
|
"features/support/REDCapDemoDatabase_DataDictionary.csv",
|
62
61
|
"features/support/env.rb",
|
63
62
|
"features/support/paths.rb",
|
63
|
+
"features/support/redcap_new_headers.csv",
|
64
64
|
"features/support/redcap_siblings.csv",
|
65
|
+
"features/support/redcap_whitespace.csv",
|
65
66
|
"features/surveyor.feature",
|
66
67
|
"features/surveyor_parser.feature",
|
67
68
|
"generators/extend_surveyor/extend_surveyor_generator.rb",
|
@@ -77,6 +78,7 @@ Gem::Specification.new do |s|
|
|
77
78
|
"generators/surveyor/templates/assets/stylesheets/dateinput.css",
|
78
79
|
"generators/surveyor/templates/assets/stylesheets/reset.css",
|
79
80
|
"generators/surveyor/templates/assets/stylesheets/results.css",
|
81
|
+
"generators/surveyor/templates/assets/stylesheets/sass/custom.sass",
|
80
82
|
"generators/surveyor/templates/assets/stylesheets/sass/surveyor.sass",
|
81
83
|
"generators/surveyor/templates/locales/surveyor_en.yml",
|
82
84
|
"generators/surveyor/templates/locales/surveyor_es.yml",
|
@@ -85,6 +87,7 @@ Gem::Specification.new do |s|
|
|
85
87
|
"generators/surveyor/templates/migrate/add_correct_answer_id_to_questions.rb",
|
86
88
|
"generators/surveyor/templates/migrate/add_default_value_to_answers.rb",
|
87
89
|
"generators/surveyor/templates/migrate/add_display_order_to_surveys.rb",
|
90
|
+
"generators/surveyor/templates/migrate/add_display_type_to_answers.rb",
|
88
91
|
"generators/surveyor/templates/migrate/add_index_to_response_sets.rb",
|
89
92
|
"generators/surveyor/templates/migrate/add_index_to_surveys.rb",
|
90
93
|
"generators/surveyor/templates/migrate/add_section_id_to_responses.rb",
|
@@ -129,6 +132,7 @@ Gem::Specification.new do |s|
|
|
129
132
|
"spec/controllers/surveyor_controller_spec.rb",
|
130
133
|
"spec/factories.rb",
|
131
134
|
"spec/helpers/surveyor_helper_spec.rb",
|
135
|
+
"spec/lib/benchmark_spec.rb",
|
132
136
|
"spec/lib/common_spec.rb",
|
133
137
|
"spec/lib/parser_spec.rb",
|
134
138
|
"spec/lib/redcap_parser_spec.rb",
|
@@ -151,6 +155,7 @@ Gem::Specification.new do |s|
|
|
151
155
|
"testbed/Gemfile"
|
152
156
|
]
|
153
157
|
s.homepage = %q{http://github.com/NUBIC/surveyor}
|
158
|
+
s.post_install_message = %q{Thanks for installing surveyor! The time has come to run the surveyor generator and migrate your database, even if you are upgrading.}
|
154
159
|
s.require_paths = ["lib"]
|
155
160
|
s.rubygems_version = %q{1.6.2}
|
156
161
|
s.summary = %q{A rails (gem) plugin to enable surveys in your application}
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: surveyor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 79
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 20
|
9
|
+
- 0
|
10
|
+
version: 0.20.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brian Chamberlain
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-
|
19
|
+
date: 2011-07-11 00:00:00 -05:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -112,7 +112,6 @@ extensions: []
|
|
112
112
|
extra_rdoc_files:
|
113
113
|
- README.md
|
114
114
|
files:
|
115
|
-
- .rvmrc
|
116
115
|
- CHANGELOG
|
117
116
|
- MIT-LICENSE
|
118
117
|
- README.md
|
@@ -158,7 +157,9 @@ files:
|
|
158
157
|
- features/support/REDCapDemoDatabase_DataDictionary.csv
|
159
158
|
- features/support/env.rb
|
160
159
|
- features/support/paths.rb
|
160
|
+
- features/support/redcap_new_headers.csv
|
161
161
|
- features/support/redcap_siblings.csv
|
162
|
+
- features/support/redcap_whitespace.csv
|
162
163
|
- features/surveyor.feature
|
163
164
|
- features/surveyor_parser.feature
|
164
165
|
- generators/extend_surveyor/extend_surveyor_generator.rb
|
@@ -174,6 +175,7 @@ files:
|
|
174
175
|
- generators/surveyor/templates/assets/stylesheets/dateinput.css
|
175
176
|
- generators/surveyor/templates/assets/stylesheets/reset.css
|
176
177
|
- generators/surveyor/templates/assets/stylesheets/results.css
|
178
|
+
- generators/surveyor/templates/assets/stylesheets/sass/custom.sass
|
177
179
|
- generators/surveyor/templates/assets/stylesheets/sass/surveyor.sass
|
178
180
|
- generators/surveyor/templates/locales/surveyor_en.yml
|
179
181
|
- generators/surveyor/templates/locales/surveyor_es.yml
|
@@ -182,6 +184,7 @@ files:
|
|
182
184
|
- generators/surveyor/templates/migrate/add_correct_answer_id_to_questions.rb
|
183
185
|
- generators/surveyor/templates/migrate/add_default_value_to_answers.rb
|
184
186
|
- generators/surveyor/templates/migrate/add_display_order_to_surveys.rb
|
187
|
+
- generators/surveyor/templates/migrate/add_display_type_to_answers.rb
|
185
188
|
- generators/surveyor/templates/migrate/add_index_to_response_sets.rb
|
186
189
|
- generators/surveyor/templates/migrate/add_index_to_surveys.rb
|
187
190
|
- generators/surveyor/templates/migrate/add_section_id_to_responses.rb
|
@@ -226,6 +229,7 @@ files:
|
|
226
229
|
- spec/controllers/surveyor_controller_spec.rb
|
227
230
|
- spec/factories.rb
|
228
231
|
- spec/helpers/surveyor_helper_spec.rb
|
232
|
+
- spec/lib/benchmark_spec.rb
|
229
233
|
- spec/lib/common_spec.rb
|
230
234
|
- spec/lib/parser_spec.rb
|
231
235
|
- spec/lib/redcap_parser_spec.rb
|
@@ -250,7 +254,7 @@ has_rdoc: true
|
|
250
254
|
homepage: http://github.com/NUBIC/surveyor
|
251
255
|
licenses: []
|
252
256
|
|
253
|
-
post_install_message:
|
257
|
+
post_install_message: Thanks for installing surveyor! The time has come to run the surveyor generator and migrate your database, even if you are upgrading.
|
254
258
|
rdoc_options: []
|
255
259
|
|
256
260
|
require_paths:
|
data/.rvmrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rvm_gemset_create_on_use_flag=1; rvm gemset use surveyor-dev
|