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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd9606811238e9bdb1b1631958b96015870257419b4c83165631028ddbf2fdd2
4
- data.tar.gz: a2604ed8e68436afbdcc4a7be836d827c9331a2610a8d245fdd04c000ff04aa7
3
+ metadata.gz: 48644d7de607c9ccde5f8314ec0ed2565924d2f83f266b7dccd03b200d0eec0b
4
+ data.tar.gz: 0afddb777531a00b7d4fbc687f38f392974262a8edb2f4a603d48022501bc043
5
5
  SHA512:
6
- metadata.gz: 701a73e5cb940b753e4bfdf618d0667fa5a2a67a5267c4fafdadb6a5213805e83971a08c333c96f46cb1ebeb76e8f308939697f4a6b184a4dd15666d0ba9253b
7
- data.tar.gz: c95e08ea6752e3c403c9abe84351cf1adb92bdfe20b249311e069c696b64266232f45a7b9276764e215e37cacc6bfb49f32c8c400971e1644aee4ad8619575a2
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
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/red_cap`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ ![CI](https://github.com/botandrose/red_cap/workflows/CI/badge.svg)
4
+ ![Coverage](https://codecov.io/gh/botandrose/red_cap/branch/master/graph/badge.svg)
4
5
 
5
- TODO: Delete this and the text above, and describe your gem
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
- ## Installation
8
+ ## Features
8
9
 
9
- Add this line to your application's Gemfile:
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
- gem 'red_cap'
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
- And then execute:
30
+ Or create instances with specific configurations:
16
31
 
17
- $ bundle
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
- Or install it yourself as:
40
+ ## Usage
20
41
 
21
- $ gem install red_cap
42
+ ### Basic Data Operations
22
43
 
23
- ## Usage
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
- TODO: Write usage instructions here
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/[USERNAME]/red_cap.
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
@@ -18,6 +18,11 @@ class REDCap
18
18
  raw
19
19
  end
20
20
  end
21
+
22
+ def self.clear
23
+ dir = "tmp/redcap_cache"
24
+ FileUtils.rm_rf dir if ::File.exist?(dir)
25
+ end
21
26
  end
22
27
  end
23
28
 
@@ -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
- full_url = @url + "?" + options.to_query
71
- json = Cache.fetch(full_url) do
72
- response = base_request(options.reverse_merge({
73
- format: "json",
74
- }))
75
- response.body
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
@@ -164,7 +164,7 @@ class REDCap
164
164
  end
165
165
  end
166
166
 
167
- if selected_options.keys.include?("501")
167
+ if selected_options(responses).keys.include?("501")
168
168
  right[-1] = [other_text_field("501")&.value(responses)]
169
169
  end
170
170
 
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
@@ -1,3 +1,3 @@
1
1
  class REDCap
2
- VERSION = "0.12.1"
2
+ VERSION = "0.13.0"
3
3
  end
data/lib/red_cap.rb CHANGED
@@ -3,6 +3,8 @@ require "red_cap/client"
3
3
  require "red_cap/form"
4
4
 
5
5
  class REDCap
6
+ autoload :InstrumentTable, "red_cap/instrument_table"
7
+
6
8
  class << self
7
9
  def configure
8
10
  yield self
data/red_cap.gemspec CHANGED
@@ -27,4 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "bundler"
28
28
  spec.add_development_dependency "rake"
29
29
  spec.add_development_dependency "rspec"
30
+ spec.add_development_dependency "simplecov"
30
31
  end
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.12.1
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: 2024-04-22 00:00:00.000000000 Z
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.32
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: []