missinglink 0.1.6
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +23 -0
- data/app/assets/javascripts/missinglink/application.js +13 -0
- data/app/assets/stylesheets/missinglink/application.css +13 -0
- data/app/controllers/missinglink/application_controller.rb +4 -0
- data/app/helpers/missinglink/application_helper.rb +4 -0
- data/app/models/missinglink/survey.rb +18 -0
- data/app/models/missinglink/survey_answer.rb +32 -0
- data/app/models/missinglink/survey_page.rb +31 -0
- data/app/models/missinglink/survey_page_question.rb +8 -0
- data/app/models/missinglink/survey_question.rb +35 -0
- data/app/models/missinglink/survey_respondent_detail.rb +45 -0
- data/app/models/missinglink/survey_response.rb +29 -0
- data/app/models/missinglink/survey_response_answer.rb +25 -0
- data/app/views/layouts/missinglink/application.html.erb +14 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20140308005724_add_missinglink_survey_schema.rb +114 -0
- data/lib/missinglink.rb +111 -0
- data/lib/missinglink/engine.rb +9 -0
- data/lib/missinglink/version.rb +3 -0
- data/lib/tasks/missinglink_tasks.rake +4 -0
- metadata +150 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b278ee350c825cbf5865a20c06323cc2760988a7
|
4
|
+
data.tar.gz: 1d12e2f05a11a165e56d4903229020a20ce1952a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b286d50f06cecd6c25726fb54857d57005177d1cbd88e5733b0d22d18fe2e52d161d7018890a70ebb1e980280f5ddd346c5402f94ee78622316884d20c8eb6d4
|
7
|
+
data.tar.gz: 1b89b1e30c1c85646b305a90820b5ff219309a74d0d0061e82025058b4ab899e8296b0c965ad48ac6341075c8a7e14557dfb2edfe2a5123469d7d8b9eb49539d
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Missinglink'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Missinglink
|
2
|
+
class Survey < ActiveRecord::Base
|
3
|
+
self.table_name = "surveys"
|
4
|
+
|
5
|
+
has_many :survey_pages
|
6
|
+
has_many :survey_questions, through: :survey_pages
|
7
|
+
has_many :survey_respondent_details
|
8
|
+
|
9
|
+
def self.first_or_create_by_sm_survey_id(sm_id)
|
10
|
+
# spelling this one out more explicitly so it's easier to test
|
11
|
+
if new_survey = Survey.find_by_sm_survey_id(sm_id.to_i)
|
12
|
+
return new_survey
|
13
|
+
else
|
14
|
+
return Survey.create(sm_survey_id: sm_id.to_i)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Missinglink
|
2
|
+
class SurveyAnswer < ActiveRecord::Base
|
3
|
+
self.table_name = "survey_answers"
|
4
|
+
|
5
|
+
belongs_to :survey_question
|
6
|
+
|
7
|
+
def self.parse(question, hash)
|
8
|
+
answer = SurveyAnswer.first_or_create_by_question_details(question.id, hash['answer_id'])
|
9
|
+
|
10
|
+
answer.update_attributes({ position: hash['position'].to_i,
|
11
|
+
text: hash['text'],
|
12
|
+
answer_type: hash['type'],
|
13
|
+
visible: hash['visible'],
|
14
|
+
weight: hash['weight'],
|
15
|
+
apply_all_rows: hash['apply_all_rows'],
|
16
|
+
is_answer: hash['is_answer'] })
|
17
|
+
|
18
|
+
answer.survey_question = question
|
19
|
+
answer.save
|
20
|
+
|
21
|
+
return answer
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.first_or_create_by_question_details(question_id, sm_id)
|
25
|
+
if new_answer = SurveyAnswer.find_by_survey_question_id_and_sm_answer_id(question_id, sm_id.to_i)
|
26
|
+
return new_answer
|
27
|
+
else
|
28
|
+
return SurveyAnswer.create(survey_question_id: question_id, sm_answer_id: sm_id.to_i)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Missinglink
|
2
|
+
class SurveyPage < ActiveRecord::Base
|
3
|
+
self.table_name = "survey_pages"
|
4
|
+
|
5
|
+
belongs_to :survey
|
6
|
+
has_many :survey_page_questions
|
7
|
+
has_many :survey_questions, through: :survey_page_questions
|
8
|
+
|
9
|
+
def self.parse(survey, hash)
|
10
|
+
page = first_or_create_by_survey_details(survey.id, hash['page_id'])
|
11
|
+
page.update_attributes({heading: hash['heading'],
|
12
|
+
sub_heading: hash['sub_heading']})
|
13
|
+
|
14
|
+
|
15
|
+
hash['questions'].each do |question|
|
16
|
+
SurveyQuestion.parse(page, question)
|
17
|
+
end
|
18
|
+
|
19
|
+
return page.reload
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.first_or_create_by_survey_details(survey_id, sm_id)
|
23
|
+
# spelling this one out more explicitly so it's easier to test
|
24
|
+
if new_page = SurveyPage.find_by_survey_id_and_sm_page_id(survey_id, sm_id.to_i)
|
25
|
+
return new_page
|
26
|
+
else
|
27
|
+
return SurveyPage.create(survey_id: survey_id, sm_page_id: sm_id.to_i)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Missinglink
|
2
|
+
class SurveyQuestion < ActiveRecord::Base
|
3
|
+
self.table_name = "survey_questions"
|
4
|
+
|
5
|
+
has_many :survey_page_questions
|
6
|
+
has_many :survey_pages, through: :survey_page_questions
|
7
|
+
has_many :survey_answers
|
8
|
+
has_many :survey_responses
|
9
|
+
|
10
|
+
def self.parse(page, hash)
|
11
|
+
question = SurveyQuestion.first_or_create_by_sm_id(hash['question_id'])
|
12
|
+
|
13
|
+
question.update_attributes({ heading: hash['heading'],
|
14
|
+
position: hash['position'].to_i,
|
15
|
+
type_family: hash['type']['family'],
|
16
|
+
type_subtype: hash['type']['subtype'] })
|
17
|
+
question.survey_pages = [page]
|
18
|
+
question.save
|
19
|
+
|
20
|
+
hash['answers'].each do |answer|
|
21
|
+
SurveyAnswer.parse(question, answer)
|
22
|
+
end
|
23
|
+
|
24
|
+
return question.reload
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.first_or_create_by_sm_id(sm_id)
|
28
|
+
if question = SurveyQuestion.find_by_sm_question_id(sm_id)
|
29
|
+
return question
|
30
|
+
else
|
31
|
+
return SurveyQuestion.create(sm_question_id: sm_id)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Missinglink
|
2
|
+
class SurveyRespondentDetail < ActiveRecord::Base
|
3
|
+
self.table_name = "survey_respondent_details"
|
4
|
+
|
5
|
+
belongs_to :survey
|
6
|
+
has_many :survey_responses
|
7
|
+
has_many :survey_response_answers, through: :survey_responses
|
8
|
+
|
9
|
+
def self.parse(survey, hash)
|
10
|
+
srd = SurveyRespondentDetail.first_or_create_by_survey_details(survey.id, hash['respondent_id'])
|
11
|
+
|
12
|
+
attrs = prepare_respondent_details(hash)
|
13
|
+
srd.update_attributes(attrs)
|
14
|
+
|
15
|
+
return srd
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.first_or_create_by_survey_details(survey_id, sm_id)
|
19
|
+
# spelling this one out more explicitly so it's easier to test
|
20
|
+
if new_srd = SurveyRespondentDetail.find_by_survey_id_and_sm_respondent_id(survey_id, sm_id.to_i)
|
21
|
+
return new_srd
|
22
|
+
else
|
23
|
+
return SurveyRespondentDetail.create(survey_id: survey_id, sm_respondent_id: sm_id.to_i)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def self.prepare_respondent_details(respondent_hash)
|
29
|
+
hash = { collection_mode: respondent_hash['collection_mode'],
|
30
|
+
custom_id: respondent_hash['custom_id'],
|
31
|
+
email: respondent_hash['email'],
|
32
|
+
first_name: respondent_hash['first_name'],
|
33
|
+
last_name: respondent_hash['last_name'],
|
34
|
+
ip_address: respondent_hash['ip_address'],
|
35
|
+
status: respondent_hash['status'] || "completed",
|
36
|
+
analysis_url: respondent_hash['analysis_url'] }
|
37
|
+
|
38
|
+
(hash[:date_start] = Date.parse(respondent_hash['date_start'])) if respondent_hash['date_start']
|
39
|
+
(hash[:date_modified] = Date.parse(respondent_hash['date_modified'])) if respondent_hash['date_modified']
|
40
|
+
(hash[:collector_id] = respondent_hash['collector_id'].to_i) if respondent_hash['collector_id']
|
41
|
+
|
42
|
+
return hash
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Missinglink
|
2
|
+
class SurveyResponse < ActiveRecord::Base
|
3
|
+
self.table_name = "survey_responses"
|
4
|
+
|
5
|
+
belongs_to :survey_respondent_detail
|
6
|
+
belongs_to :survey_question
|
7
|
+
has_many :survey_response_answers
|
8
|
+
|
9
|
+
def self.parse(survey, hash)
|
10
|
+
respondent = SurveyRespondentDetail.find_by_sm_respondent_id(hash['respondent_id'].to_i)
|
11
|
+
hash['questions'].each do |question_hash|
|
12
|
+
question = SurveyQuestion.find_by_sm_question_id(question_hash['question_id'])
|
13
|
+
response = SurveyResponse.first_or_create_by_respondent_and_question(respondent.id, question.id)
|
14
|
+
question_hash['answers'].each do |answer_hash|
|
15
|
+
SurveyResponseAnswer.parse(response, answer_hash)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.first_or_create_by_respondent_and_question(respondent_id, question_id)
|
21
|
+
if new_response = SurveyResponse.find_by_survey_respondent_detail_id_and_survey_question_id(respondent_id.to_i, question_id.to_i)
|
22
|
+
return new_response
|
23
|
+
else
|
24
|
+
return SurveyResponse.create(survey_respondent_detail_id: respondent_id.to_i,
|
25
|
+
survey_question_id: question_id.to_i)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Missinglink
|
2
|
+
class SurveyResponseAnswer < ActiveRecord::Base
|
3
|
+
self.table_name = "survey_response_answers"
|
4
|
+
|
5
|
+
belongs_to :survey_response
|
6
|
+
|
7
|
+
def self.parse(response, hash)
|
8
|
+
answer = SurveyResponseAnswer.create({survey_response_id: response.id}.
|
9
|
+
merge(prepare_answer_hash(hash)))
|
10
|
+
|
11
|
+
return answer
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def self.prepare_answer_hash(hash)
|
16
|
+
clean_hash = {}
|
17
|
+
clean_hash['row_survey_answer_id'] = SurveyAnswer.find_by_sm_answer_id(hash['row'].to_i).id if (hash['row'] && hash['row'] != "0")
|
18
|
+
clean_hash['col_survey_answer_id'] = SurveyAnswer.find_by_sm_answer_id(hash['col'].to_i).id if hash['col']
|
19
|
+
clean_hash['col_choice_survey_answer_id'] = SurveyAnswer.find_by_sm_answer_id(hash['col_choice'].to_i).id if hash['col_choice']
|
20
|
+
clean_hash['text'] = hash['text'] if hash['text']
|
21
|
+
|
22
|
+
return clean_hash
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Missinglink</title>
|
5
|
+
<%= stylesheet_link_tag "missinglink/application", media: "all" %>
|
6
|
+
<%= javascript_include_tag "missinglink/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
class AddMissinglinkSurveySchema < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :surveys do |t|
|
4
|
+
t.column :sm_survey_id, :bigint
|
5
|
+
t.string :analysis_url
|
6
|
+
t.timestamp :date_created
|
7
|
+
t.timestamp :date_modified
|
8
|
+
t.string :title
|
9
|
+
t.integer :language_id
|
10
|
+
t.string :nickname
|
11
|
+
t.boolean :title_enabled
|
12
|
+
t.string :title_text
|
13
|
+
|
14
|
+
t.timestamps
|
15
|
+
end
|
16
|
+
|
17
|
+
add_index :surveys, :sm_survey_id
|
18
|
+
|
19
|
+
create_table :survey_pages do |t|
|
20
|
+
t.integer :survey_id
|
21
|
+
t.column :sm_page_id, :bigint
|
22
|
+
t.text :heading
|
23
|
+
t.text :sub_heading
|
24
|
+
|
25
|
+
t.timestamps
|
26
|
+
end
|
27
|
+
|
28
|
+
add_index :survey_pages, :survey_id
|
29
|
+
add_index :survey_pages, :sm_page_id
|
30
|
+
|
31
|
+
create_table :survey_page_questions do |t|
|
32
|
+
t.integer :survey_page_id
|
33
|
+
t.integer :survey_question_id
|
34
|
+
|
35
|
+
t.timestamps
|
36
|
+
end
|
37
|
+
|
38
|
+
add_index :survey_page_questions, :survey_page_id
|
39
|
+
add_index :survey_page_questions, :survey_question_id
|
40
|
+
|
41
|
+
create_table :survey_questions do |t|
|
42
|
+
t.column :sm_question_id, :bigint
|
43
|
+
t.text :heading
|
44
|
+
t.integer :position
|
45
|
+
t.string :type_family
|
46
|
+
t.string :type_subtype
|
47
|
+
|
48
|
+
t.timestamps
|
49
|
+
end
|
50
|
+
|
51
|
+
add_index :survey_questions, :sm_question_id
|
52
|
+
|
53
|
+
create_table :survey_answers do |t|
|
54
|
+
t.column :sm_answer_id, :bigint
|
55
|
+
t.integer :survey_question_id
|
56
|
+
t.integer :position
|
57
|
+
t.text :text
|
58
|
+
t.string :answer_type
|
59
|
+
t.boolean :visible
|
60
|
+
t.integer :weight
|
61
|
+
t.boolean :apply_all_rows
|
62
|
+
t.boolean :is_answer
|
63
|
+
|
64
|
+
t.timestamps
|
65
|
+
end
|
66
|
+
|
67
|
+
add_index :survey_answers, :sm_answer_id
|
68
|
+
add_index :survey_answers, :survey_question_id
|
69
|
+
|
70
|
+
create_table :survey_respondent_details do |t|
|
71
|
+
t.integer :survey_id
|
72
|
+
t.column :sm_respondent_id, :bigint
|
73
|
+
t.timestamp :date_start
|
74
|
+
t.timestamp :date_modified
|
75
|
+
t.integer :collector_id
|
76
|
+
t.string :collection_mode
|
77
|
+
t.string :custom_id
|
78
|
+
t.string :email
|
79
|
+
t.string :first_name
|
80
|
+
t.string :last_name
|
81
|
+
t.string :ip_address
|
82
|
+
t.string :status
|
83
|
+
t.string :analysis_url
|
84
|
+
|
85
|
+
t.timestamps
|
86
|
+
end
|
87
|
+
|
88
|
+
add_index :survey_respondent_details, :survey_id
|
89
|
+
add_index :survey_respondent_details, :sm_respondent_id
|
90
|
+
add_index :survey_respondent_details, :email
|
91
|
+
|
92
|
+
create_table :survey_responses do |t|
|
93
|
+
t.integer :survey_respondent_detail_id
|
94
|
+
t.integer :survey_question_id
|
95
|
+
|
96
|
+
t.timestamps
|
97
|
+
end
|
98
|
+
|
99
|
+
add_index :survey_responses, :survey_respondent_detail_id
|
100
|
+
add_index :survey_responses, :survey_question_id
|
101
|
+
|
102
|
+
create_table :survey_response_answers do |t|
|
103
|
+
t.integer :survey_response_id
|
104
|
+
t.integer :row_survey_answer_id
|
105
|
+
t.integer :col_survey_answer_id
|
106
|
+
t.integer :col_choice_survey_answer_id
|
107
|
+
t.text :text
|
108
|
+
|
109
|
+
t.timestamps
|
110
|
+
end
|
111
|
+
|
112
|
+
add_index :survey_response_answers, :survey_response_id
|
113
|
+
end
|
114
|
+
end
|
data/lib/missinglink.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require "missinglink/engine"
|
2
|
+
require 'typhoeus'
|
3
|
+
|
4
|
+
module Missinglink
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def poll_surveys(credential_hash = { api_key: nil, token: nil })
|
8
|
+
unless (api_key = credential_hash[:api_key]) && (token = credential_hash[:token])
|
9
|
+
puts "Please provide a hash with api_key and token to poll surveys."
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
response = JSON.parse(typh_request('get_survey_list', api_key, token).tap {|x| x.run}.response.body)['data']['surveys']
|
14
|
+
response.each do |s|
|
15
|
+
survey = Survey.first_or_create_by_sm_survey_id(s['survey_id'].to_i)
|
16
|
+
survey.update_attributes(analysis_url: s['analysis_url'])
|
17
|
+
fetch_survey(survey, credential_hash)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def fetch_survey(survey, credential_hash)
|
22
|
+
unless (api_key = credential_hash[:api_key]) && (token = credential_hash[:token])
|
23
|
+
puts "Please provide a hash with api_key and token to fetch surveys."
|
24
|
+
return
|
25
|
+
end
|
26
|
+
|
27
|
+
request = typh_request('get_survey_details', api_key, token, {survey_id: survey.sm_survey_id.to_s}.to_json).tap { |x| x.run }
|
28
|
+
response = JSON.parse(request.response.body)['data']
|
29
|
+
|
30
|
+
survey.update_attributes({date_created: DateTime.parse(response['date_created']),
|
31
|
+
date_modified: DateTime.parse(response['date_modified']),
|
32
|
+
title: response['title']['text'],
|
33
|
+
language_id: response['language_id'].to_i,
|
34
|
+
nickname: response['nickname'],
|
35
|
+
title_enabled: response['title']['enabled'],
|
36
|
+
title_text: response['title']['text']})
|
37
|
+
|
38
|
+
response['pages'].each do |page|
|
39
|
+
SurveyPage.parse(survey, page)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def fetch_respondents(survey, credential_hash = { api_key: nil, token: nil })
|
44
|
+
unless (api_key = credential_hash[:api_key]) && (token = credential_hash[:token])
|
45
|
+
puts "Please provide a hash with api_key and token to fetch survey respondents."
|
46
|
+
return
|
47
|
+
end
|
48
|
+
|
49
|
+
request = typh_request('get_respondent_list', api_key, token, {survey_id: survey.sm_survey_id.to_s}.to_json).tap { |x| x.run }
|
50
|
+
respondents = JSON.parse(request.response.body)['data']['respondents']
|
51
|
+
respondents.each do |respondent|
|
52
|
+
SurveyRespondentDetail.parse(survey, respondent)
|
53
|
+
end
|
54
|
+
|
55
|
+
fetch_responses(survey.reload, credential_hash)
|
56
|
+
end
|
57
|
+
|
58
|
+
def fetch_responses(survey, credential_hash)
|
59
|
+
unless (api_key = credential_hash[:api_key]) && (token = credential_hash[:token])
|
60
|
+
puts "Please provide a hash with api_key and token to fetch survey responses."
|
61
|
+
return
|
62
|
+
end
|
63
|
+
|
64
|
+
# to start, we will only pull down completed surveys, and not re-pull these surveys
|
65
|
+
# if a respondent is complete and has no response, then we need to pull it down
|
66
|
+
# if a respodnent is complete and has a response, then we will not re-pull, it's done
|
67
|
+
|
68
|
+
respondents = SurveyRespondentDetail.where(survey_id: survey.id,
|
69
|
+
status: "completed")
|
70
|
+
|
71
|
+
respondents_to_pull = respondents.select { |r| r.survey_responses.empty? }
|
72
|
+
|
73
|
+
fetch_response_answers(survey, respondents_to_pull, credential_hash)
|
74
|
+
end
|
75
|
+
|
76
|
+
def fetch_response_answers(survey, respondents, credential_hash)
|
77
|
+
unless (api_key = credential_hash[:api_key]) && (token = credential_hash[:token])
|
78
|
+
puts "Please provide a hash with api_key and token to fetch survey response answers."
|
79
|
+
return
|
80
|
+
end
|
81
|
+
|
82
|
+
while (respondents.size > 0)
|
83
|
+
ids = respondents.slice!(0, 100).map { |x| x.sm_respondent_id.to_s }
|
84
|
+
request = typh_request('get_responses', api_key, token,
|
85
|
+
{ survey_id: survey.sm_survey_id.to_s,
|
86
|
+
respondent_ids: ids }.to_json).tap { |x| x.run }
|
87
|
+
response = JSON.parse(request.response.body)['data']
|
88
|
+
|
89
|
+
response.each do |r|
|
90
|
+
begin
|
91
|
+
SurveyResponse.parse(survey, r) unless r.nil?
|
92
|
+
rescue Exception => e
|
93
|
+
raise "Error processing Survey Response for survey #{ survey.inspect }\n\nResponse hash: #{ response.inspect }\n\nAttempting to parse: #{ r.inspect }\n\nException: #{ e.inspect }"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
def typh_request(fragment, api_key, token, body = '{ }')
|
101
|
+
sleep 0.5 # survey monkey's API limits are obnoxious, this is hacky but an easy way to ensure that we're always under
|
102
|
+
# the 2 QPS limit
|
103
|
+
Typhoeus::Request.new(
|
104
|
+
"https://api.surveymonkey.net/v2/surveys/#{fragment}",
|
105
|
+
method: :post,
|
106
|
+
params: { api_key: api_key },
|
107
|
+
body: body,
|
108
|
+
headers: { Authorization: "bearer #{token}", :"Content-Type" => "application/json" }
|
109
|
+
)
|
110
|
+
end
|
111
|
+
end
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: missinglink
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Trey Springer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sqlite3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.14'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.14'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: webmock
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.17'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.17'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: vcr
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.8'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.8'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: typhoeus
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.6'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.6'
|
97
|
+
description: This gem, when installed, enables pulling down surveys, questions, and
|
98
|
+
responses from the SurveyMonkey API.
|
99
|
+
email:
|
100
|
+
- trey@mustwin.com
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- MIT-LICENSE
|
106
|
+
- Rakefile
|
107
|
+
- app/assets/javascripts/missinglink/application.js
|
108
|
+
- app/assets/stylesheets/missinglink/application.css
|
109
|
+
- app/controllers/missinglink/application_controller.rb
|
110
|
+
- app/helpers/missinglink/application_helper.rb
|
111
|
+
- app/models/missinglink/survey.rb
|
112
|
+
- app/models/missinglink/survey_answer.rb
|
113
|
+
- app/models/missinglink/survey_page.rb
|
114
|
+
- app/models/missinglink/survey_page_question.rb
|
115
|
+
- app/models/missinglink/survey_question.rb
|
116
|
+
- app/models/missinglink/survey_respondent_detail.rb
|
117
|
+
- app/models/missinglink/survey_response.rb
|
118
|
+
- app/models/missinglink/survey_response_answer.rb
|
119
|
+
- app/views/layouts/missinglink/application.html.erb
|
120
|
+
- config/routes.rb
|
121
|
+
- db/migrate/20140308005724_add_missinglink_survey_schema.rb
|
122
|
+
- lib/missinglink.rb
|
123
|
+
- lib/missinglink/engine.rb
|
124
|
+
- lib/missinglink/version.rb
|
125
|
+
- lib/tasks/missinglink_tasks.rake
|
126
|
+
homepage: https://github.com/MustWin/missinglink
|
127
|
+
licenses:
|
128
|
+
- MIT
|
129
|
+
metadata: {}
|
130
|
+
post_install_message:
|
131
|
+
rdoc_options: []
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
requirements: []
|
145
|
+
rubyforge_project:
|
146
|
+
rubygems_version: 2.2.0
|
147
|
+
signing_key:
|
148
|
+
specification_version: 4
|
149
|
+
summary: Wrapper around the SurveyMonkey v2 API.
|
150
|
+
test_files: []
|