surveyor 0.19.7 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|