red_cap 0.12.1 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +32 -0
- data/README.md +128 -12
- data/lib/red_cap/cache.rb +5 -0
- data/lib/red_cap/client.rb +11 -9
- data/lib/red_cap/form/fields.rb +1 -1
- data/lib/red_cap/form.rb +3 -2
- data/lib/red_cap/instrument_table.rb +58 -0
- data/lib/red_cap/version.rb +1 -1
- data/lib/red_cap.rb +2 -0
- data/red_cap.gemspec +1 -0
- metadata +19 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48644d7de607c9ccde5f8314ec0ed2565924d2f83f266b7dccd03b200d0eec0b
|
4
|
+
data.tar.gz: 0afddb777531a00b7d4fbc687f38f392974262a8edb2f4a603d48022501bc043
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16463efe4a464d37ad171101b596afa9b958419e2452d08269d87f0e227de6e5e528420b9e3749570724798dab6971cef234f36ced87fb94c44f7d67129f1777
|
7
|
+
data.tar.gz: 07eff14d151bd692e8a12375aeac8191e291e7c95fcc31ed92aeed02353cd117e33423a84fa5f9b2c13144b811523b3b9cdc479f0ca097e38395372be09855f9
|
@@ -0,0 +1,32 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
|
9
|
+
strategy:
|
10
|
+
fail-fast: false
|
11
|
+
matrix:
|
12
|
+
ruby: ['3.2', '3.3', '3.4']
|
13
|
+
|
14
|
+
steps:
|
15
|
+
- uses: actions/checkout@v4
|
16
|
+
|
17
|
+
- name: Set up Ruby ${{ matrix.ruby }}
|
18
|
+
uses: ruby/setup-ruby@v1
|
19
|
+
with:
|
20
|
+
ruby-version: ${{ matrix.ruby }}
|
21
|
+
bundler-cache: true
|
22
|
+
|
23
|
+
- name: Run tests
|
24
|
+
run: bundle exec rake spec
|
25
|
+
|
26
|
+
- name: Upload coverage to Codecov
|
27
|
+
if: matrix.ruby == '3.3'
|
28
|
+
uses: codecov/codecov-action@v5
|
29
|
+
with:
|
30
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
31
|
+
file: ./coverage/coverage.xml
|
32
|
+
fail_ci_if_error: false
|
data/README.md
CHANGED
@@ -1,28 +1,144 @@
|
|
1
1
|
# REDCap
|
2
2
|
|
3
|
-
|
3
|
+

|
4
|
+

|
4
5
|
|
5
|
-
|
6
|
+
A Ruby client library for connecting to REDCap (Research Electronic Data Capture) and parsing forms and data. REDCap is a secure web application for building and managing online surveys and databases, particularly for research studies.
|
6
7
|
|
7
|
-
##
|
8
|
+
## Features
|
8
9
|
|
9
|
-
|
10
|
+
- **REDCap API Integration**: Full client for REDCap's API endpoints
|
11
|
+
- **Form Parsing**: Dynamic form handling with Ruby-friendly field access
|
12
|
+
- **Field Type Support**: Comprehensive support for REDCap field types (text, radio buttons, checkboxes, dropdowns, etc.)
|
13
|
+
- **Caching**: Optional response caching for improved performance
|
14
|
+
- **Batch Operations**: Efficient handling of large datasets with pagination
|
15
|
+
- **File Handling**: Support for file uploads and downloads
|
16
|
+
|
17
|
+
## Configuration
|
18
|
+
|
19
|
+
Configure the gem globally:
|
10
20
|
|
11
21
|
```ruby
|
12
|
-
|
22
|
+
REDCap.configure do |config|
|
23
|
+
config.url = "https://your-redcap-instance.org/api/"
|
24
|
+
config.token = "your_api_token_here"
|
25
|
+
config.per_page = 100 # optional, defaults to 100
|
26
|
+
config.cache = true # optional, defaults to nil (no caching)
|
27
|
+
end
|
13
28
|
```
|
14
29
|
|
15
|
-
|
30
|
+
Or create instances with specific configurations:
|
16
31
|
|
17
|
-
|
32
|
+
```ruby
|
33
|
+
client = REDCap.new(
|
34
|
+
url: "https://your-redcap-instance.org/api/",
|
35
|
+
token: "your_api_token_here",
|
36
|
+
per_page: 50
|
37
|
+
)
|
38
|
+
```
|
18
39
|
|
19
|
-
|
40
|
+
## Usage
|
20
41
|
|
21
|
-
|
42
|
+
### Basic Data Operations
|
22
43
|
|
23
|
-
|
44
|
+
```ruby
|
45
|
+
# Find a specific record
|
46
|
+
record = client.find("study_id_001")
|
47
|
+
|
48
|
+
# Get all records (with block for memory efficiency)
|
49
|
+
client.all do |record|
|
50
|
+
puts record["study_id"]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Get all records as array
|
54
|
+
records = client.all
|
55
|
+
|
56
|
+
# Filter records
|
57
|
+
client.where(status: 1, age: 25) do |record|
|
58
|
+
puts record["name"]
|
59
|
+
end
|
60
|
+
|
61
|
+
# Update a record
|
62
|
+
client.update("study_id_001", { name: "John Doe", age: 30 })
|
63
|
+
|
64
|
+
# Delete a record
|
65
|
+
client.delete("study_id_001")
|
66
|
+
```
|
67
|
+
|
68
|
+
### Working with Forms
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
# Access the form structure
|
72
|
+
form = client.form
|
73
|
+
|
74
|
+
# Access field values with dynamic methods
|
75
|
+
form.responses = record_data
|
76
|
+
puts form.participant_name # accesses field "participant_name"
|
77
|
+
puts form.age # accesses field "age"
|
78
|
+
puts form.consent_date # accesses field "consent_date"
|
79
|
+
|
80
|
+
# Check field types
|
81
|
+
field = form.fields.find { |f| f.field_name == "gender" }
|
82
|
+
puts field.radio? # true if radio button field
|
83
|
+
puts field.checkbox? # true if checkbox field
|
84
|
+
puts field.field_type # "radio", "checkbox", etc.
|
85
|
+
```
|
86
|
+
|
87
|
+
### Field Types
|
88
|
+
|
89
|
+
The gem supports various REDCap field types with appropriate Ruby representations:
|
90
|
+
|
91
|
+
- **Text fields**: Return string values
|
92
|
+
- **Yes/No fields**: Return boolean values
|
93
|
+
- **Radio buttons**: Return selected option text
|
94
|
+
- **Checkboxes**: Return array of selected options
|
95
|
+
- **Dropdowns**: Return selected option text
|
96
|
+
- **Files**: Return field name if file exists
|
97
|
+
|
98
|
+
### Advanced Field Access
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
# Override field type interpretation
|
102
|
+
form.my_field(as: :radio_buttons)
|
103
|
+
|
104
|
+
# Access with options
|
105
|
+
form.checkbox_field(default: false)
|
106
|
+
```
|
107
|
+
|
108
|
+
### File Handling
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
# Download a file
|
112
|
+
file = client.client.file("record_id", "file_field_name")
|
113
|
+
puts file.filename
|
114
|
+
puts file.type
|
115
|
+
# file.data contains the file content
|
116
|
+
```
|
117
|
+
|
118
|
+
### Caching
|
119
|
+
|
120
|
+
Enable caching to improve performance for repeated API calls:
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
REDCap.configure do |config|
|
124
|
+
config.cache = true
|
125
|
+
end
|
126
|
+
|
127
|
+
# Clear cache when needed
|
128
|
+
REDCap::Cache.clear
|
129
|
+
```
|
130
|
+
|
131
|
+
## Field Types Reference
|
24
132
|
|
25
|
-
|
133
|
+
| REDCap Type | Ruby Class | Return Value |
|
134
|
+
| ------------- | ------------------- | -------------------------- |
|
135
|
+
| text | Text | String |
|
136
|
+
| notes | Notes | String |
|
137
|
+
| yesno | Yesno | Boolean |
|
138
|
+
| radio | RadioButtons | String (selected option) |
|
139
|
+
| dropdown | Dropdown | String (selected option) |
|
140
|
+
| checkbox | CheckboxesWithOther | Array of strings |
|
141
|
+
| file | File | String (field name) or nil |
|
26
142
|
|
27
143
|
## Development
|
28
144
|
|
@@ -32,7 +148,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
148
|
|
33
149
|
## Contributing
|
34
150
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
151
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/botandrose/red_cap.
|
36
152
|
|
37
153
|
## License
|
38
154
|
|
data/lib/red_cap/cache.rb
CHANGED
data/lib/red_cap/client.rb
CHANGED
@@ -55,8 +55,6 @@ class REDCap
|
|
55
55
|
|
56
56
|
File = Struct.new(:data, :type, :filename)
|
57
57
|
|
58
|
-
private
|
59
|
-
|
60
58
|
def fetch_study_ids filter=nil
|
61
59
|
json_api_request({
|
62
60
|
content: "record",
|
@@ -66,17 +64,21 @@ class REDCap
|
|
66
64
|
end
|
67
65
|
|
68
66
|
require "active_support/core_ext/object/to_query"
|
69
|
-
def json_api_request options
|
70
|
-
|
71
|
-
json =
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
67
|
+
def json_api_request options, cache: false
|
68
|
+
request_options = options.reverse_merge(format: "json")
|
69
|
+
json = if cache
|
70
|
+
full_url = @url + "?" + options.to_query
|
71
|
+
Cache.fetch(full_url) do
|
72
|
+
base_request(request_options).body
|
73
|
+
end
|
74
|
+
else
|
75
|
+
base_request(request_options).body
|
76
76
|
end
|
77
77
|
JSON.load(json)
|
78
78
|
end
|
79
79
|
|
80
|
+
private
|
81
|
+
|
80
82
|
def base_request options
|
81
83
|
connection = Faraday.new(url: @url)
|
82
84
|
connection.options.open_timeout = 300
|
data/lib/red_cap/form/fields.rb
CHANGED
data/lib/red_cap/form.rb
CHANGED
@@ -3,8 +3,9 @@ require "active_support/core_ext/string/inflections"
|
|
3
3
|
|
4
4
|
class REDCap
|
5
5
|
class Form
|
6
|
-
def initialize data_dictionary
|
6
|
+
def initialize data_dictionary, responses=nil
|
7
7
|
@data_dictionary = data_dictionary
|
8
|
+
@responses = responses
|
8
9
|
end
|
9
10
|
|
10
11
|
attr_accessor :data_dictionary, :responses
|
@@ -27,7 +28,7 @@ class REDCap
|
|
27
28
|
def find_field key, field_class, options
|
28
29
|
field = fields.find { |field| field.field_name == key }
|
29
30
|
field = field_class.new(field.attributes) if field_class
|
30
|
-
field.options = options
|
31
|
+
field.options = options if field
|
31
32
|
field
|
32
33
|
end
|
33
34
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class REDCap
|
2
|
+
class InstrumentTable < ActiveRecord::Base
|
3
|
+
self.table_name = :redcap_instrument_tables
|
4
|
+
|
5
|
+
class_attribute :config
|
6
|
+
def self.pulls_from config
|
7
|
+
self.config = config.reverse_merge({
|
8
|
+
key: :study_id,
|
9
|
+
repeating: false,
|
10
|
+
})
|
11
|
+
|
12
|
+
config[:fields].each do |field|
|
13
|
+
define_method field do
|
14
|
+
value = form.send(field)
|
15
|
+
value.define_singleton_method :var do
|
16
|
+
"#{config[:instrument_name]}.#{field}"
|
17
|
+
end
|
18
|
+
value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.pull client, filter={}
|
24
|
+
filter.reverse_merge!({
|
25
|
+
content: "record",
|
26
|
+
events: Array(config[:events] || config[:event]).join(","),
|
27
|
+
fields: [config[:key]] + config[:fields],
|
28
|
+
})
|
29
|
+
|
30
|
+
metadata = client.json_api_request({
|
31
|
+
content: "metadata",
|
32
|
+
fields: config[:fields],
|
33
|
+
}, cache: true)
|
34
|
+
|
35
|
+
client.json_api_request(filter).map do |response|
|
36
|
+
if config[:repeating]
|
37
|
+
next unless response["redcap_repeat_instrument"] == config[:instrument_name]
|
38
|
+
repeat_instance = response["redcap_repeat_instance"]
|
39
|
+
end
|
40
|
+
record = where({
|
41
|
+
instrument_name: config[:instrument_name],
|
42
|
+
repeat_instance: repeat_instance,
|
43
|
+
event: response.fetch("redcap_event_name"),
|
44
|
+
key: response.fetch(config[:key].to_s),
|
45
|
+
}).first_or_initialize
|
46
|
+
record.update!({
|
47
|
+
fields: response,
|
48
|
+
metadata: metadata,
|
49
|
+
})
|
50
|
+
record
|
51
|
+
end.compact
|
52
|
+
end
|
53
|
+
|
54
|
+
def form
|
55
|
+
@form ||= REDCap::Form.new(metadata, fields)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/red_cap/version.rb
CHANGED
data/lib/red_cap.rb
CHANGED
data/red_cap.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: red_cap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Micah Geisel
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-09-14 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: faraday
|
@@ -80,6 +79,20 @@ dependencies:
|
|
80
79
|
- - ">="
|
81
80
|
- !ruby/object:Gem::Version
|
82
81
|
version: '0'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: simplecov
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
83
96
|
description: Library for connecting to REDCap and parsing forms and data
|
84
97
|
email:
|
85
98
|
- micah@botandrose.com
|
@@ -87,6 +100,7 @@ executables: []
|
|
87
100
|
extensions: []
|
88
101
|
extra_rdoc_files: []
|
89
102
|
files:
|
103
|
+
- ".github/workflows/ci.yml"
|
90
104
|
- ".gitignore"
|
91
105
|
- ".rspec"
|
92
106
|
- ".travis.yml"
|
@@ -101,13 +115,13 @@ files:
|
|
101
115
|
- lib/red_cap/client.rb
|
102
116
|
- lib/red_cap/form.rb
|
103
117
|
- lib/red_cap/form/fields.rb
|
118
|
+
- lib/red_cap/instrument_table.rb
|
104
119
|
- lib/red_cap/version.rb
|
105
120
|
- red_cap.gemspec
|
106
121
|
homepage: https://github.com/botandrose/red_cap
|
107
122
|
licenses:
|
108
123
|
- MIT
|
109
124
|
metadata: {}
|
110
|
-
post_install_message:
|
111
125
|
rdoc_options: []
|
112
126
|
require_paths:
|
113
127
|
- lib
|
@@ -122,8 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
136
|
- !ruby/object:Gem::Version
|
123
137
|
version: '0'
|
124
138
|
requirements: []
|
125
|
-
rubygems_version: 3.2
|
126
|
-
signing_key:
|
139
|
+
rubygems_version: 3.6.2
|
127
140
|
specification_version: 4
|
128
141
|
summary: Library for connecting to REDCap and parsing forms and data
|
129
142
|
test_files: []
|