redcap-survey-api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ /*.gem
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 mmcrockett
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,35 @@
1
+ # Usage
2
+
3
+ This is an api to utilize RedCAP api with ruby.
4
+
5
+ To start:
6
+
7
+ Test cases are the best place to look for examples. Here are some simple examples.
8
+
9
+ ```ruby
10
+ r = RedcapSurveyApi::RedcapApi.new({:token => "abc123", :url => "http://localhost/redcap/api"}) # Authentication token provided by RedCAP, server API url.
11
+ r = RedcapSurveyApi::RedcapApi.new({:token => "abc123", :url => "http://localhost/redcap/api", :parser => JSON}) # Set the parser, default is JSON, other parsers are Nokogiri::XML, CSV, RedcapSurveyApi::EmptyParser. See tests for examples.
12
+
13
+ r.export() # returns all records in 'parser' format, provide additional hash of parameters in you want to override or add any additional RedCAP options.
14
+
15
+ r.export_metadata() # returns all metadata records in JSON format, provide additional hash of parameters in you want to override or add any additional RedCAP options.
16
+
17
+ r.export_metadata_fields() # returns all fields (this is a sub-set of metadata).
18
+
19
+ r.import() # imports new records.
20
+
21
+ r.export({:parser => RedcapSurveyApi::EmptyParser}) # returns the raw data, this allows you to get data without going through the parser.
22
+
23
+ There is also a helper class added to ruby Hash allowing you to convert a ruby array to a http-post style array. I created this after having some issues filtering on 'forms' and 'fields'
24
+ Example:
25
+ params = {:fields => ['record_id', 'lab_id'], :forms => ['slide_tracking', 'id_shipping']} # This is the data I want to send to RedCAP, limiting the fields and forms
26
+ r.export_metadata(params.to_http_post_array()) # This gets the metadata for only those fields/forms by using the newly added method on Hash 'to_http_post_array'.
27
+ ```
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it ( https://github.com/[my-github-username]/redcap-survey-api/fork )
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Create a new Pull Request
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ end
7
+
8
+ desc "Run tests"
9
+ task :default => :test
@@ -0,0 +1,59 @@
1
+ require 'json'
2
+ require 'mechanize'
3
+ require 'redcap-survey-api/hash_extension'
4
+ require 'redcap-survey-api/empty_parser'
5
+
6
+ module RedcapSurveyApi
7
+ class RedcapApi
8
+ DEFAULT_PARAMS = {
9
+ :content => 'record',
10
+ :format => 'json',
11
+ :type => 'flat',
12
+ :parser => JSON
13
+ }
14
+
15
+ def initialize(params = {})
16
+ @payload = DEFAULT_PARAMS.merge(params)
17
+ end
18
+
19
+ def export(params = {})
20
+ return api(params)
21
+ end
22
+
23
+ def export_metadata(params = {})
24
+ payload = {:content => 'metadata'}.merge(params)
25
+ return export(payload)
26
+ end
27
+
28
+ def export_metadata_fields
29
+ response = export_metadata()
30
+ if response
31
+ response.collect {|r| r['field_name'] if r }
32
+ end
33
+ end
34
+
35
+ def import(params = {})
36
+ return api(params)
37
+ end
38
+
39
+ private
40
+ def api(params = {})
41
+ payload = @payload.merge(params)
42
+ validate(payload)
43
+
44
+ return payload[:parser].parse(Mechanize.new.post(@url, payload).body)
45
+ end
46
+
47
+ def validate(params)
48
+ [:token, :url].each do |required_param|
49
+ if (false == params.include?(required_param))
50
+ raise "!ERROR: '#{required_param}' is a required parameter."
51
+ end
52
+ end
53
+
54
+ if ((false == "#{params[:parser]}".include?("EmptyParser")) && (false == "#{params[:parser]}".downcase.include?(params[:format])))
55
+ $stderr.puts "!WARNING: Your parser '#{params[:parser]}' and your default format '#{params[:format]}' don't seem to match."
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,7 @@
1
+ module RedcapSurveyApi
2
+ class EmptyParser
3
+ def self.parse(data)
4
+ return data
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ class Hash
2
+ def to_http_post_array
3
+ r = {}
4
+
5
+ self.each_key do |k|
6
+ if (false == self[k].is_a?(Array))
7
+ raise "!ERROR: Expecting hash value to be an Array."
8
+ end
9
+
10
+ self[k].each_with_index do |v,i|
11
+ r["#{k}[#{i}]"] = v
12
+ end
13
+ end
14
+
15
+ return r
16
+ end
17
+ end
@@ -0,0 +1,24 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'redcap-survey-api'
3
+ s.version = '0.0.1'
4
+ s.platform = Gem::Platform::RUBY
5
+ s.homepage = "https://github.com/mmcrockett/redcap-survey-api"
6
+ s.date = '2014-09-02'
7
+ s.summary = %q{REDCap Survey API - Welcome to easy interaction with REDCap through Ruby.}
8
+ s.description = %q{REDCap Survey API provides a ruby-style interface for interacting with the REDCap survey system from Vanderbilt.}
9
+ s.authors = ["Mike Crockett"]
10
+ s.email = "redcap@mmcrockett.com"
11
+ s.license = "MIT"
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = ["lib"]
17
+ s.extra_rdoc_files = ["README.md"]
18
+
19
+ s.add_development_dependency "rake"
20
+ s.add_development_dependency "csv"
21
+ s.add_development_dependency "nokogiri"
22
+ s.add_dependency "mechanize"
23
+ s.add_dependency "json"
24
+ end
@@ -0,0 +1,29 @@
1
+ require 'test/unit'
2
+
3
+ class RedcapSurveyApiTest < Test::Unit::TestCase
4
+ def test_no_url
5
+ begin
6
+ RedcapSurveyApi::RedcapApi.new({:token => "blah"}).export()
7
+ rescue => e
8
+ end
9
+
10
+ assert_equal("!ERROR: 'url' is a required parameter.", "#{e}")
11
+ end
12
+
13
+ def test_no_token
14
+ begin
15
+ RedcapSurveyApi::RedcapApi.new({:url => "lala"}).export()
16
+ rescue => e
17
+ end
18
+
19
+ assert_equal("!ERROR: 'token' is a required parameter.", "#{e}")
20
+ end
21
+
22
+ def test_warning
23
+ $stderr = StringIO.open('','w')
24
+
25
+ RedcapSurveyApi::RedcapApi.new({:token => "x", :url => "y", :format => 'invalid'}).export()
26
+
27
+ assert_equal("!WARNING: Your parser 'JSON' and your default format 'invalid' don't seem to match.", $stderr.string.chomp)
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ require 'test/unit'
2
+
3
+ class RedcapSurveyHashExtensionTest < Test::Unit::TestCase
4
+ def test_hash_extension
5
+ t = {:a => [1,2,3], :b => ["h", "i", "j"]}
6
+ e = {"a[0]" => 1, "a[1]" => 2, "a[2]" => 3, "b[0]" => "h", "b[1]" => "i", "b[2]" => "j"}
7
+ assert_equal(e, t.to_http_post_array)
8
+ end
9
+ end
@@ -0,0 +1,110 @@
1
+ require 'test/unit'
2
+ require 'redcap-survey-api'
3
+ require 'csv'
4
+ require 'Nokogiri'
5
+ require 'StringIO'
6
+
7
+ class Hash
8
+ def body
9
+ return self[:body]
10
+ end
11
+ end
12
+
13
+ class Mechanize
14
+ def post(url, payload)
15
+ v = {}
16
+
17
+ if ('json' == payload[:format])
18
+ if ('metadata' == payload[:content])
19
+ v[:body] = '[{"field_name":"record_id", "form_name":"form0"},{"field_name":"first_name", "form_name":"form0"},{"field_name":"trc_id", "form_name":"form0"}]'
20
+ else
21
+ v[:body] = '[{"record_id":"1", "trc_id":"b", "first_name":"bob"},{"record_id":"2", "trc_id":"c", "first_name":"chris"}]'
22
+ end
23
+ elsif ('xml' == payload[:format])
24
+ v[:body] = '<?xml version="1.0" encoding="UTF-8" ?><records><item><record_id><![CDATA[1]]></record_id><trc_id>b</trc_id><first_name>bob</first_name></item><item><record_id><![CDATA[2]]></record_id><trc_id>c</trc_id><first_name>chris</first_name></item></records>'
25
+ elsif ('csv' == payload[:format])
26
+ v[:body] = 'record_id,trc_id,first_name'
27
+ v[:body] << "\n"
28
+ v[:body] << '"1","b","bob"'
29
+ v[:body] << "\n"
30
+ v[:body] << '"2","c","chris"'
31
+ else
32
+ v[:body] = '[{"record_id":"1", "trc_id":"b", "first_name":"bob"},{"record_id":"2", "trc_id":"c", "first_name":"chris"}]'
33
+ end
34
+
35
+ return v
36
+ end
37
+ end
38
+
39
+ class RedcapSurveyApiTest < Test::Unit::TestCase
40
+ DEFAULT_CONNECTION = {:url => "http://localhost:8080/redcap/api", :token => "ABC123"}
41
+
42
+ def test_default_parser
43
+ default = RedcapSurveyApi::RedcapApi.new(DEFAULT_CONNECTION).export()
44
+ json_data = RedcapSurveyApi::RedcapApi.new(DEFAULT_CONNECTION.merge({:parser => JSON})).export({:format => 'json'})
45
+
46
+ assert_equal(json_data, default)
47
+ end
48
+
49
+ def test_xml_parser
50
+ xml_data = RedcapSurveyApi::RedcapApi.new(DEFAULT_CONNECTION.merge({:parser => Nokogiri::XML::Document})).export({:format => 'xml'})
51
+ json_data = RedcapSurveyApi::RedcapApi.new(DEFAULT_CONNECTION.merge({:parser => JSON})).export({:format => 'json'})
52
+ xml_to_json_data = []
53
+
54
+ xml_data.xpath(".//item").each do |item_node|
55
+ json_record = {}
56
+ item_node.children().each do |value_node|
57
+ json_record[value_node.name()] = value_node.content()
58
+ end
59
+ xml_to_json_data << json_record
60
+ end
61
+
62
+ assert_equal(json_data, xml_to_json_data)
63
+ end
64
+
65
+ def test_csv_parser
66
+ csv_data = RedcapSurveyApi::RedcapApi.new(DEFAULT_CONNECTION.merge({:parser => CSV})).export({:format => 'csv'})
67
+ json_data = RedcapSurveyApi::RedcapApi.new(DEFAULT_CONNECTION.merge({:parser => JSON})).export({:format => 'json'})
68
+ csv_to_json_data = []
69
+
70
+ csv_data.each_with_index do |record,i|
71
+ if (0 != i)
72
+ json_record = {}
73
+ record.each_with_index do |value,j|
74
+ json_record[csv_data[0][j]] = value
75
+ end
76
+ csv_to_json_data << json_record
77
+ end
78
+ end
79
+
80
+ assert_equal(json_data, csv_to_json_data)
81
+ end
82
+
83
+ def test_none_parser
84
+ $stderr = StringIO.open('','w')
85
+ none_data = RedcapSurveyApi::RedcapApi.new(DEFAULT_CONNECTION.merge({:parser => RedcapSurveyApi::EmptyParser})).export({:format => 'xml'})
86
+
87
+ assert_equal('<?xml version="1.0" encoding="UTF-8" ?><records><item><record_id><![CDATA[1]]></record_id><trc_id>b</trc_id><first_name>bob</first_name></item><item><record_id><![CDATA[2]]></record_id><trc_id>c</trc_id><first_name>chris</first_name></item></records>', none_data)
88
+ assert_equal("", $stderr.string.chomp)
89
+ end
90
+
91
+ def test_param_override
92
+ metadata = RedcapSurveyApi::RedcapApi.new(DEFAULT_CONNECTION).export_metadata()
93
+ data = RedcapSurveyApi::RedcapApi.new(DEFAULT_CONNECTION).export_metadata({:content => 'record'})
94
+
95
+ assert_not_equal(data, metadata)
96
+ end
97
+
98
+ def test_metadata
99
+ metadata = RedcapSurveyApi::RedcapApi.new(DEFAULT_CONNECTION).export_metadata()
100
+ data = [{"field_name"=>"record_id", "form_name"=>"form0"},{"field_name"=>"first_name", "form_name"=>"form0"},{"field_name"=>"trc_id", "form_name"=>"form0"}]
101
+
102
+ assert_equal(data, metadata)
103
+ end
104
+
105
+ def test_metadata_fields
106
+ fields = RedcapSurveyApi::RedcapApi.new(DEFAULT_CONNECTION).export_metadata_fields()
107
+
108
+ assert_equal(["record_id", "first_name", "trc_id"], fields)
109
+ end
110
+ end
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redcap-survey-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mike Crockett
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-09-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: csv
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: nokogiri
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: mechanize
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: json
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: REDCap Survey API provides a ruby-style interface for interacting with
95
+ the REDCap survey system from Vanderbilt.
96
+ email: redcap@mmcrockett.com
97
+ executables: []
98
+ extensions: []
99
+ extra_rdoc_files:
100
+ - README.md
101
+ files:
102
+ - .gitignore
103
+ - LICENSE.txt
104
+ - README.md
105
+ - Rakefile
106
+ - lib/redcap-survey-api.rb
107
+ - lib/redcap-survey-api/empty_parser.rb
108
+ - lib/redcap-survey-api/hash_extension.rb
109
+ - redcap-survey-api.gemspec
110
+ - test/test_errors_and_warnings.rb
111
+ - test/test_hash_extension.rb
112
+ - test/test_redcap_api.rb
113
+ homepage: https://github.com/mmcrockett/redcap-survey-api
114
+ licenses:
115
+ - MIT
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 1.8.24
135
+ signing_key:
136
+ specification_version: 3
137
+ summary: REDCap Survey API - Welcome to easy interaction with REDCap through Ruby.
138
+ test_files:
139
+ - test/test_errors_and_warnings.rb
140
+ - test/test_hash_extension.rb
141
+ - test/test_redcap_api.rb