RedcapAPI 0.0.5 → 0.0.6a
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/README.md +57 -2
- data/Rakefile +7 -0
- data/RedcapAPI.gemspec +6 -13
- data/lib/RedcapAPI.rb +52 -9
- data/lib/RedcapAPI/version.rb +1 -1
- data/test/test_redcap_api.rb +105 -0
- metadata +61 -23
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NWU2OGY2NmExMTM1YjY2ZjgzOTRmYmZjZTM2ZjBkZjg5MWNhYmFjOQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3ecc5ee19022a7fe8d9bd20f08fb53039a48716b
|
4
|
+
data.tar.gz: 75037075c22cd9bac02d65cbc2e72b0c48ccf742
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
MDhmYmE2ZmNhNTVmMGM0YmE2M2I0ODYyYjliNmIyYzczZTFmYzRiMDkzOGUy
|
11
|
-
YjU5MmZhOGJmZDQyOGM2ZGFjMTk3ZWU1MzgwZGQxNWQ2YzRhZTg=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
YWQ0ODcyNGNiYTI3NmEyMmIwMjAwZGE1YWNiZjkyNWU2YmM5NDllOGZmNjI3
|
14
|
-
NDM2NWM2ODRmY2FjNGU1ZGM4MjY2MDFjNDZiOWE2NjljMTY5YTlmZmRmNDRh
|
15
|
-
N2NlNWJhODJhYjY5YjAwMTAwNWZlMmIzM2IxODFhMTg0NWNlMmE=
|
6
|
+
metadata.gz: 4dabdab78f3a6409c34be703e68496441aed72fe378c7675ee7b05c46c0fed8b81b3da5074de123ecf691cdc8147e2ea2e93aa597d22cb4b278612b6455867fc
|
7
|
+
data.tar.gz: da28bddc0d8b639195a157713f7ac9348b1eb09ba6b3513e77e9a722b22b227ffe234b16cbf76c6a3fd998129e87b32bbc72ad4f4ef8fef2a3b744a4f18872ef
|
data/README.md
CHANGED
@@ -3,11 +3,66 @@
|
|
3
3
|
This is an api to utilize REDCAP api with ruby. This Gem requires mechanize as a dependency.
|
4
4
|
it is based on instructions here http://sburns.org/2013/07/22/intro-to-redcap-api.html
|
5
5
|
|
6
|
+
This gem is under development and testing. If you would like to make changes or have comments, reach me at eugene@tranquiltech.io
|
7
|
+
|
8
|
+
Special thanks to mmcrockett for making great additions.
|
9
|
+
|
6
10
|
To start:
|
11
|
+
```ruby
|
12
|
+
r = RedcapAPI.new(token, url, parser)
|
13
|
+
```
|
14
|
+
your institution has it's own url, and each project has it's own token, an optional 'parser' that defaults to JSON. See the test cases for how to use other parsers like Nokogiri::XML and CSV.
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
r.export(optional params)
|
18
|
+
```
|
19
|
+
returns all records in JSON format, provide additional hash of parameters in you want to override or add any additional RedcapAPI options.
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
r.export_metadata(optional params)
|
23
|
+
```
|
24
|
+
returns all metadata records in JSON format, provide additional hash of parameters in you want to override or add any additional RedcapAPI options.
|
25
|
+
|
26
|
+
```
|
27
|
+
r.import(optional params)
|
28
|
+
```
|
29
|
+
imports new records, the 'post' method is likely more helpful as it puts the 'data' in the correct format.
|
30
|
+
|
31
|
+
```
|
32
|
+
r.api(optional params)
|
33
|
+
```
|
34
|
+
returns the raw data, this allows you to return 'xml' or 'csv' instead of forcing 'json'. Simply override the params. Example r.api({:format => 'xml'}).
|
35
|
+
```
|
36
|
+
r.get(optional record_id)
|
37
|
+
```
|
38
|
+
returns all records in JSON format or a specific record if specified
|
39
|
+
```
|
40
|
+
r.get_fields
|
41
|
+
```
|
42
|
+
returns all fields for that instrument
|
43
|
+
```
|
44
|
+
r.post(data)
|
45
|
+
```
|
46
|
+
this will either update an old record or create a new one. the data should be in form of array of hashes or as a hash (for one item). dates are accepted in Date class or in strftime('%F') format.
|
47
|
+
for example
|
48
|
+
```
|
49
|
+
data = {name: 'this is a test', field_2: Date.today}
|
50
|
+
r.post(data)
|
51
|
+
```
|
52
|
+
creates a new object using the fields above. field names must match those in the existing project
|
53
|
+
"{\"count\": 1}" --> indicates the object posted.
|
7
54
|
|
8
|
-
|
55
|
+
to update an existing record:
|
56
|
+
```
|
57
|
+
data = {record_id: 3, name: 'this is a test to update', field_2: Date.today}
|
58
|
+
r.post(data)
|
59
|
+
```
|
60
|
+
this will update the record with record_id 3. if record_id 3 does not exist it will create an entry with that record id
|
9
61
|
|
10
|
-
|
62
|
+
There is also a helper class added to ruby Hash allowing you to convert a ruby array to a http-post style array. It was created after having some issues filtering on 'forms' and 'fields'
|
63
|
+
Example:
|
64
|
+
params = {:fields => ['record_id', 'lab_id'], :forms => ['slide_tracking', 'id_shipping']} # This is the data I want to send to RedcapAPI, limiting the fields and forms
|
65
|
+
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'.
|
11
66
|
|
12
67
|
## Contributing
|
13
68
|
|
data/Rakefile
CHANGED
data/RedcapAPI.gemspec
CHANGED
@@ -9,20 +9,10 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["eugyev"]
|
10
10
|
spec.email = ["eugyev@gmail.com"]
|
11
11
|
spec.summary = %q{This is an api to utilize REDCAP api with ruby. This Gem requires mechanize as a dependency.
|
12
|
-
|
12
|
+
The backend is based on instructions here http://sburns.org/2013/07/22/intro-to-redcap-api.html
|
13
13
|
}
|
14
14
|
spec.description = %q{
|
15
|
-
|
16
|
-
|
17
|
-
To start:
|
18
|
-
|
19
|
-
r = RedcapAPI.new(token, url) # your institution has it's own url, and each project has it's own token
|
20
|
-
|
21
|
-
r.get(optional record_id) # returns all records in JSON format or a specific record if specified
|
22
|
-
|
23
|
-
r.get_fields # returns all fields for that instrument
|
24
|
-
|
25
|
-
r.post(data) # this will either update an old record or create a new one. the data should be in form of array of hashes or as a hash (for one item). dates are accepted in Date class or in strftime('%F') format.
|
15
|
+
Please see Github Repo and Readme file https://github.com/eugyev/RedcapAPI
|
26
16
|
}
|
27
17
|
spec.homepage = ""
|
28
18
|
spec.license = "MIT"
|
@@ -34,5 +24,8 @@ Gem::Specification.new do |spec|
|
|
34
24
|
|
35
25
|
spec.add_development_dependency "bundler", "~> 1.6"
|
36
26
|
spec.add_development_dependency "rake"
|
37
|
-
spec.add_development_dependency "
|
27
|
+
spec.add_development_dependency "csv"
|
28
|
+
spec.add_development_dependency "nokogiri"
|
29
|
+
spec.add_dependency "mechanize"
|
30
|
+
spec.add_dependency "json"
|
38
31
|
end
|
data/lib/RedcapAPI.rb
CHANGED
@@ -1,13 +1,40 @@
|
|
1
1
|
require "RedcapAPI/version"
|
2
|
+
require "json"
|
3
|
+
require "mechanize"
|
4
|
+
class Hash
|
5
|
+
def to_http_post_array
|
6
|
+
r = {}
|
7
|
+
|
8
|
+
self.each_key do |k|
|
9
|
+
if (false == self[k].is_a?(Array))
|
10
|
+
raise "!ERROR: Expecting hash value to be an Array."
|
11
|
+
end
|
12
|
+
|
13
|
+
self[k].each_with_index do |v,i|
|
14
|
+
r["#{k}[#{i}]"] = v
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
return r
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
2
22
|
class RedcapAPI
|
3
|
-
|
4
|
-
|
5
|
-
|
23
|
+
DEFAULT_PARAMS = {
|
24
|
+
:content => 'record',
|
25
|
+
:format => 'json',
|
26
|
+
:type => 'flat'
|
27
|
+
}
|
28
|
+
|
29
|
+
def initialize(token, url, parser = JSON)
|
30
|
+
@url = url
|
31
|
+
@payload = DEFAULT_PARAMS
|
32
|
+
@payload[:token] = token
|
33
|
+
@parser = parser
|
6
34
|
end
|
7
35
|
|
8
36
|
def get(record_id = nil)
|
9
|
-
|
10
|
-
data = JSON.parse Mechanize.new.post(@url, payload).body
|
37
|
+
data = self.export()
|
11
38
|
if record_id
|
12
39
|
data = data.select{|x| x['record_id'] == record_id.to_s}
|
13
40
|
end
|
@@ -15,8 +42,7 @@ require "RedcapAPI/version"
|
|
15
42
|
end
|
16
43
|
|
17
44
|
def get_fields
|
18
|
-
|
19
|
-
response = JSON.parse Mechanize.new.post(@url, payload).body
|
45
|
+
response = export_metadata()
|
20
46
|
if response
|
21
47
|
response.collect {|r| r['field_name'] if r }
|
22
48
|
end
|
@@ -25,8 +51,7 @@ require "RedcapAPI/version"
|
|
25
51
|
def post(data)
|
26
52
|
data = filter_data(data)
|
27
53
|
data_string = data.to_json
|
28
|
-
|
29
|
-
Mechanize.new.post(@url, payload).body
|
54
|
+
return self.import({:data => data_string})
|
30
55
|
end
|
31
56
|
|
32
57
|
def filter_data(data)
|
@@ -56,4 +81,22 @@ require "RedcapAPI/version"
|
|
56
81
|
(max_entry.to_i + 1).to_s
|
57
82
|
end
|
58
83
|
end
|
84
|
+
|
85
|
+
def export(params = {})
|
86
|
+
return @parser.parse(api(params))
|
87
|
+
end
|
88
|
+
|
89
|
+
def export_metadata(params = {})
|
90
|
+
payload = {:content => 'metadata'}.merge(params)
|
91
|
+
return self.export(payload)
|
92
|
+
end
|
93
|
+
|
94
|
+
def import(params = {})
|
95
|
+
return api(params)
|
96
|
+
end
|
97
|
+
|
98
|
+
def api(params = {})
|
99
|
+
payload = @payload.merge(params)
|
100
|
+
return Mechanize.new.post(@url, payload).body
|
101
|
+
end
|
59
102
|
end
|
data/lib/RedcapAPI/version.rb
CHANGED
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'RedcapAPI'
|
3
|
+
require 'csv'
|
4
|
+
require 'Nokogiri'
|
5
|
+
|
6
|
+
class Hash
|
7
|
+
def body
|
8
|
+
return self[:body]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Mechanize
|
13
|
+
def post(url, payload)
|
14
|
+
v = {}
|
15
|
+
|
16
|
+
if ('json' == payload[:format])
|
17
|
+
if ('metadata' == payload[:content])
|
18
|
+
v[:body] = '[{"field_name":"record_id", "form_name":"form0"},{"field_name":"first_name", "form_name":"form0"},{"field_name":"trc_id", "form_name":"form0"}]'
|
19
|
+
else
|
20
|
+
v[:body] = '[{"record_id":"1", "trc_id":"b", "first_name":"bob"},{"record_id":"2", "trc_id":"c", "first_name":"chris"}]'
|
21
|
+
end
|
22
|
+
elsif ('xml' == payload[:format])
|
23
|
+
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>'
|
24
|
+
elsif ('csv' == payload[:format])
|
25
|
+
v[:body] = 'record_id,trc_id,first_name'
|
26
|
+
v[:body] << "\n"
|
27
|
+
v[:body] << '"1","b","bob"'
|
28
|
+
v[:body] << "\n"
|
29
|
+
v[:body] << '"2","c","chris"'
|
30
|
+
else
|
31
|
+
raise "!ERROR: unkown format '#{payload[:format]}'."
|
32
|
+
end
|
33
|
+
|
34
|
+
return v
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class RedcapAPITest < Test::Unit::TestCase
|
39
|
+
def test_hash_extension
|
40
|
+
t = {:a => [1,2,3], :b => ["h", "i", "j"]}
|
41
|
+
e = {"a[0]" => 1, "a[1]" => 2, "a[2]" => 3, "b[0]" => "h", "b[1]" => "i", "b[2]" => "j"}
|
42
|
+
assert_equal(e, t.to_http_post_array)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_default_parser
|
46
|
+
default = RedcapAPI.new("", "").export()
|
47
|
+
json_data = RedcapAPI.new("", "", JSON).export({:format => 'json'})
|
48
|
+
|
49
|
+
assert_equal(json_data, default)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_xml_parser
|
53
|
+
xml_data = RedcapAPI.new("", "", Nokogiri::XML::Document).export({:format => 'xml'})
|
54
|
+
json_data = RedcapAPI.new("", "", JSON).export({:format => 'json'})
|
55
|
+
xml_to_json_data = []
|
56
|
+
|
57
|
+
xml_data.xpath(".//item").each do |item_node|
|
58
|
+
json_record = {}
|
59
|
+
item_node.children().each do |value_node|
|
60
|
+
json_record[value_node.name()] = value_node.content()
|
61
|
+
end
|
62
|
+
xml_to_json_data << json_record
|
63
|
+
end
|
64
|
+
|
65
|
+
assert_equal(json_data, xml_to_json_data)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_csv_parser
|
69
|
+
csv_data = RedcapAPI.new("", "", CSV).export({:format => 'csv'})
|
70
|
+
json_data = RedcapAPI.new("", "", JSON).export({:format => 'json'})
|
71
|
+
csv_to_json_data = []
|
72
|
+
|
73
|
+
csv_data.each_with_index do |record,i|
|
74
|
+
if (0 != i)
|
75
|
+
json_record = {}
|
76
|
+
record.each_with_index do |value,j|
|
77
|
+
json_record[csv_data[0][j]] = value
|
78
|
+
end
|
79
|
+
csv_to_json_data << json_record
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
assert_equal(json_data, csv_to_json_data)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_param_override
|
87
|
+
metadata = RedcapAPI.new("", "").export_metadata()
|
88
|
+
data = RedcapAPI.new("", "").export_metadata({:content => 'record'})
|
89
|
+
|
90
|
+
assert_not_equal(data, metadata)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_metadata
|
94
|
+
metadata = RedcapAPI.new("", "").export_metadata()
|
95
|
+
data = [{"field_name"=>"record_id", "form_name"=>"form0"},{"field_name"=>"first_name", "form_name"=>"form0"},{"field_name"=>"trc_id", "form_name"=>"form0"}]
|
96
|
+
|
97
|
+
assert_equal(data, metadata)
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_get_fields
|
101
|
+
fields = RedcapAPI.new("", "").get_fields()
|
102
|
+
|
103
|
+
assert_equal(["record_id", "first_name", "trc_id"], fields)
|
104
|
+
end
|
105
|
+
end
|
metadata
CHANGED
@@ -1,72 +1,108 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: RedcapAPI
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6a
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- eugyev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.6'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.6'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: csv
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: nokogiri
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mechanize
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
53
81
|
- !ruby/object:Gem::Version
|
54
82
|
version: '0'
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: json
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: "\n Please see Github Repo and Readme file https://github.com/eugyev/RedcapAPI\n
|
98
|
+
\ "
|
63
99
|
email:
|
64
100
|
- eugyev@gmail.com
|
65
101
|
executables: []
|
66
102
|
extensions: []
|
67
103
|
extra_rdoc_files: []
|
68
104
|
files:
|
69
|
-
- .gitignore
|
105
|
+
- ".gitignore"
|
70
106
|
- Gemfile
|
71
107
|
- LICENSE.txt
|
72
108
|
- README.md
|
@@ -74,6 +110,7 @@ files:
|
|
74
110
|
- RedcapAPI.gemspec
|
75
111
|
- lib/RedcapAPI.rb
|
76
112
|
- lib/RedcapAPI/version.rb
|
113
|
+
- test/test_redcap_api.rb
|
77
114
|
homepage: ''
|
78
115
|
licenses:
|
79
116
|
- MIT
|
@@ -84,19 +121,20 @@ require_paths:
|
|
84
121
|
- lib
|
85
122
|
required_ruby_version: !ruby/object:Gem::Requirement
|
86
123
|
requirements:
|
87
|
-
- -
|
124
|
+
- - ">="
|
88
125
|
- !ruby/object:Gem::Version
|
89
126
|
version: '0'
|
90
127
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
128
|
requirements:
|
92
|
-
- -
|
129
|
+
- - ">"
|
93
130
|
- !ruby/object:Gem::Version
|
94
|
-
version:
|
131
|
+
version: 1.3.1
|
95
132
|
requirements: []
|
96
133
|
rubyforge_project:
|
97
134
|
rubygems_version: 2.2.2
|
98
135
|
signing_key:
|
99
136
|
specification_version: 4
|
100
137
|
summary: This is an api to utilize REDCAP api with ruby. This Gem requires mechanize
|
101
|
-
as a dependency.
|
102
|
-
test_files:
|
138
|
+
as a dependency. The backend is based on instructions here http://sburns.org/2013/07/22/intro-to-redcap-api.html
|
139
|
+
test_files:
|
140
|
+
- test/test_redcap_api.rb
|