roqua-csv_export 0.1.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 +7 -0
- data/README.md +44 -0
- data/Rakefile +43 -0
- data/lib/roqua-csv_export.rb +3 -0
- data/lib/roqua/csv_export.rb +82 -0
- data/lib/roqua/csv_export/config.rb +38 -0
- data/lib/roqua/csv_export/csv_export_questionnaire_version.rb +109 -0
- data/lib/roqua/csv_export/export_versions.rb +49 -0
- data/lib/roqua/csv_export/meta_data.rb +115 -0
- data/lib/roqua/csv_export/models.rb +22 -0
- data/lib/roqua/csv_export/models/dossier.rb +7 -0
- data/lib/roqua/csv_export/models/measurement.rb +8 -0
- data/lib/roqua/csv_export/models/non_response.rb +7 -0
- data/lib/roqua/csv_export/models/professional.rb +7 -0
- data/lib/roqua/csv_export/models/protocol.rb +7 -0
- data/lib/roqua/csv_export/models/respondent.rb +22 -0
- data/lib/roqua/csv_export/models/response.rb +60 -0
- data/lib/roqua/csv_export/models/response_flag.rb +7 -0
- data/lib/roqua/csv_export/models/response_score.rb +7 -0
- data/lib/roqua/csv_export/models/response_textvar.rb +7 -0
- data/lib/roqua/csv_export/models/response_value.rb +7 -0
- data/lib/roqua/csv_export/models/team.rb +7 -0
- data/lib/roqua/csv_export/version.rb +7 -0
- metadata +191 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4a79aadf9c4962f616080afd55cf135bc0cb2e6dbf434f39a4503bcf33059561
|
4
|
+
data.tar.gz: e0b88f7020f55e3d66987bd847360648e1cf49f0ade702455878452978ac466e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6e933d46c4d967409656f0498ce46daee0f61a50222d0d9587283fa411e8d7dc7753170d12c5ff825e93850306a20196776be5f734cd3e5fbcdcc774a61e05b9
|
7
|
+
data.tar.gz: f7d8c837215327291c4622a1608a7bcc5cf836d3936c4cafb86aa98fd92fec4d56280f3f2b46059cac45d7cf93c5083fb9f515fe8d4f2ac21b23aae62c4e4ef7
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Roqua CSV export from sqlite export
|
2
|
+
|
3
|
+
## Description
|
4
|
+
|
5
|
+
Takes a sqlite export and some export_version definitions and generates a csv file for each questionnaire in each version.
|
6
|
+
|
7
|
+
## Examples
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
require 'roqua-csv_export'
|
11
|
+
Roqua::CsvExport.generate sqlite_path: Pathname.new('spec/fixtures/sql_export.db'),
|
12
|
+
export_versions_path: Pathname.new('spec/fixtures/export_versions'),
|
13
|
+
output_path: Pathname.new('tmp/data_exports'),
|
14
|
+
organization_key: 'demo',
|
15
|
+
anonymous_data_in_exports: false # the default.
|
16
|
+
```
|
17
|
+
|
18
|
+
See [generate method](docs/Roqua/CsvExport#generate-class_method)
|
19
|
+
|
20
|
+
## Requirements
|
21
|
+
|
22
|
+
## Install
|
23
|
+
|
24
|
+
$ gem install roqua-csv_export
|
25
|
+
|
26
|
+
## Developing
|
27
|
+
|
28
|
+
* Download source
|
29
|
+
* run `bundle`
|
30
|
+
* run `guard`
|
31
|
+
* write your test and see them fail
|
32
|
+
* write your code until the spec pass.
|
33
|
+
|
34
|
+
## Changelog
|
35
|
+
|
36
|
+
### 0.1.0
|
37
|
+
|
38
|
+
First version.
|
39
|
+
|
40
|
+
## Copyright
|
41
|
+
|
42
|
+
Copyright (c) 2017 Roqua
|
43
|
+
|
44
|
+
See {file:LICENSE.txt} for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# encoding: utf-8
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'bundler'
|
9
|
+
rescue LoadError => e
|
10
|
+
warn e.message
|
11
|
+
warn "Run `gem install bundler` to install Bundler."
|
12
|
+
exit(-1)
|
13
|
+
end
|
14
|
+
|
15
|
+
begin
|
16
|
+
Bundler.setup(:development)
|
17
|
+
rescue Bundler::BundlerError => e
|
18
|
+
warn e.message
|
19
|
+
warn "Run `bundle install` to install missing gems."
|
20
|
+
exit e.status_code
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rake'
|
24
|
+
|
25
|
+
require 'rspec/core/rake_task'
|
26
|
+
RSpec::Core::RakeTask.new
|
27
|
+
|
28
|
+
task test: :spec
|
29
|
+
task default: :spec
|
30
|
+
|
31
|
+
# run bundle in parent dir to update Gemfile.lock
|
32
|
+
task :release do
|
33
|
+
Bundler.with_clean_env do
|
34
|
+
`bundle --gemfile=../Gemfile`
|
35
|
+
end
|
36
|
+
`git add ../Gemfile.lock && git commit -m 'update roqua-csv_export in Gemfile.lock'`
|
37
|
+
end
|
38
|
+
|
39
|
+
require "bundler/gem_tasks"
|
40
|
+
|
41
|
+
require 'yard'
|
42
|
+
YARD::Rake::YardocTask.new
|
43
|
+
task doc: :yard
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/core_ext/object'
|
5
|
+
require 'sequel'
|
6
|
+
require 'roqua/csv_export/version'
|
7
|
+
require 'roqua/csv_export/models'
|
8
|
+
|
9
|
+
module Roqua
|
10
|
+
module CsvExport
|
11
|
+
extend ActiveSupport::Autoload
|
12
|
+
|
13
|
+
autoload :CsvExportQuestionnaireVersion
|
14
|
+
autoload :ExportVersions
|
15
|
+
autoload :MetaData
|
16
|
+
autoload :Config
|
17
|
+
|
18
|
+
DB = Sequel.sqlite
|
19
|
+
|
20
|
+
# Generate te export files.
|
21
|
+
# When done, output_path will contain a directory for each export_version.
|
22
|
+
# Each directory will contain csv file for each questionnare.
|
23
|
+
# @see Config#initialize Config for list of attributes
|
24
|
+
def self.generate(**attrs)
|
25
|
+
require 'csv'
|
26
|
+
require 'json'
|
27
|
+
config = Config.new(**attrs)
|
28
|
+
load_db(DB, config.sqlite_path)
|
29
|
+
create_indexes
|
30
|
+
|
31
|
+
FileUtils.mkdir_p config.output_path
|
32
|
+
do_export config.export_versions, config
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def self.load_db(db, path)
|
38
|
+
source = SQLite3::Database.new(path.to_s)
|
39
|
+
|
40
|
+
db.synchronize do |memory_db|
|
41
|
+
backup = SQLite3::Backup.new(memory_db, 'main', source, 'main')
|
42
|
+
backup.step(-1)
|
43
|
+
backup.finish
|
44
|
+
end
|
45
|
+
ensure
|
46
|
+
source.close
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.create_indexes
|
50
|
+
Sequel.extension :migration
|
51
|
+
Sequel.migration do
|
52
|
+
change do
|
53
|
+
alter_table(:responses) do
|
54
|
+
add_index :questionnaire_key
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.questionnaire_keys
|
61
|
+
Models::Response.distinct.select_map(:questionnaire_key)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.do_export(export_versions, config)
|
65
|
+
questionnaire_keys.each do |questionnaire_key|
|
66
|
+
responses = CsvExport::Models::Response \
|
67
|
+
.eager(:dossier, :team, :entered_by, :respondent, :response_values, :response_flags, :response_textvars, :team, measurement: :protocol)
|
68
|
+
.where(questionnaire_key: questionnaire_key)
|
69
|
+
.order(:id)
|
70
|
+
|
71
|
+
CsvExportQuestionnaireVersion.with_versions_for(questionnaire_key,
|
72
|
+
config) do |versions|
|
73
|
+
responses.paged_each do |response|
|
74
|
+
versions.each do |version|
|
75
|
+
version.write_response(response)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Roqua::CsvExport
|
4
|
+
# Configuration for an export run.
|
5
|
+
# Each argument to new has a corresponding getter, with export_versions using export_versions_path to load the data.
|
6
|
+
class Config
|
7
|
+
ATTRS = %i(sqlite_path
|
8
|
+
export_versions
|
9
|
+
export_versions_path
|
10
|
+
organization_key
|
11
|
+
output_path
|
12
|
+
anonymous_data_in_exports)
|
13
|
+
|
14
|
+
attr_reader *ATTRS
|
15
|
+
|
16
|
+
# @param sqlite_path [Pathname] full path to sql_export.db.
|
17
|
+
# @param export_versions [ExportVersions] the versions to export. Can pass path instead.
|
18
|
+
# @param export_versions_path [Pathname] path to directory with json files, to load export_versions from.
|
19
|
+
# @param organization_key [String] will be prepended to csv_file_names.
|
20
|
+
# @param output_path [Pathname] to write a directory per export_version to.
|
21
|
+
# @param anonymous_data_in_exports [Boolean] when true, external_identifier and respondent#id will be exported
|
22
|
+
# for anonymous responses.
|
23
|
+
def initialize(sqlite_path:,
|
24
|
+
export_versions: nil,
|
25
|
+
export_versions_path: nil,
|
26
|
+
organization_key:,
|
27
|
+
output_path:,
|
28
|
+
anonymous_data_in_exports: false)
|
29
|
+
local_variables.each do |attr|
|
30
|
+
instance_variable_set("@#{attr}", binding.local_variable_get(attr))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def export_versions
|
35
|
+
@export_versions ||= ::Roqua::CsvExport::ExportVersions.new(export_versions_path)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Roqua::CsvExport
|
4
|
+
# Used to write a single csv file for one export_version of one questionnaire.
|
5
|
+
#
|
6
|
+
class CsvExportQuestionnaireVersion
|
7
|
+
attr_reader :config
|
8
|
+
|
9
|
+
# For each version in export_versions, call {.open}, yield the instances and {#close} them.
|
10
|
+
#
|
11
|
+
# @yield [questionnaire_versions]
|
12
|
+
# @yieldparam version [Array<CsvExportQuestionnaireVersion>]
|
13
|
+
# @return [void]
|
14
|
+
def self.with_versions_for(questionnaire_key, config)
|
15
|
+
versions = config.export_versions.keys.map do |export_version_key|
|
16
|
+
open export_version_key,
|
17
|
+
export_version_mapping: config.export_versions.mapping_for(questionnaire_key, export_version_key),
|
18
|
+
config: config
|
19
|
+
end.compact
|
20
|
+
|
21
|
+
yield versions
|
22
|
+
|
23
|
+
ensure
|
24
|
+
|
25
|
+
versions&.each do |version|
|
26
|
+
version.close
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Creates new object with given params and calls #open on it.
|
31
|
+
# @return [CsvExportQuestionnaireVersion]
|
32
|
+
def self.open(*args)
|
33
|
+
self.new(*args).tap do |questionnaire_version|
|
34
|
+
questionnaire_version.open
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param export_version_key [String] used to build directory name.
|
39
|
+
# @param export_version_mapping [Array<Hash>] Information on each column for the csv file in order.
|
40
|
+
# @param config [Config]
|
41
|
+
# @see ExportVersions#[] ExportsVersions for format of mapping.
|
42
|
+
def initialize(export_version_key, export_version_mapping:, config:)
|
43
|
+
@config = config
|
44
|
+
@export_version_key = export_version_key
|
45
|
+
@export_version_mapping = export_version_mapping
|
46
|
+
end
|
47
|
+
|
48
|
+
# opens file to write and writes headers to it.
|
49
|
+
# @return [void]
|
50
|
+
def open
|
51
|
+
`mkdir -p #{export_version_path}`
|
52
|
+
@file = CSV.open(csv_path, "w", col_sep: ';', force_quotes: true)
|
53
|
+
@file << export_version_mapping.map { |column| column['header'] }
|
54
|
+
end
|
55
|
+
|
56
|
+
# write the respomse to the file in the format of export_version
|
57
|
+
# @param response [Models::Response]
|
58
|
+
def write_response(response)
|
59
|
+
file << export_version_mapping \
|
60
|
+
.map { |column| get_value(column, response) }
|
61
|
+
.map { |value| format(value) }
|
62
|
+
end
|
63
|
+
|
64
|
+
# close the file.
|
65
|
+
# @return [void]
|
66
|
+
def close
|
67
|
+
file.close
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
attr_reader :export_version_key,
|
73
|
+
:export_version_mapping,
|
74
|
+
:file
|
75
|
+
|
76
|
+
def export_version_path
|
77
|
+
config.output_path.join("#{config.organization_key}_#{export_version_key}")
|
78
|
+
end
|
79
|
+
|
80
|
+
def csv_path
|
81
|
+
# find questionnaire key for the export_version (should be added explicitly to export_version json)
|
82
|
+
path_key = export_version_mapping.find{ |m| m['key'] == 'completed_at'}['header'][0..-14]
|
83
|
+
export_version_path.join("#{path_key}_#{Time.now.strftime("%Y-%m-%d")}.csv")
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_value(column, response)
|
87
|
+
case column['source_type']
|
88
|
+
when 'metadata' then MetaData.send(column['key'], response)
|
89
|
+
when 'variable' then response.variable(column['key'])
|
90
|
+
when 'score' then response.score(column['key'], column['sub_key'])
|
91
|
+
when 'flag' then response.flag(column['key']) == '1' ? 'true' : ''
|
92
|
+
when 'textvar' then response.textvar(column['key'])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def format(value)
|
97
|
+
case value
|
98
|
+
when Time, Date, DateTime
|
99
|
+
value.strftime("%d-%m-%Y %H:%M:%S")
|
100
|
+
when Hash
|
101
|
+
value.to_json
|
102
|
+
when String
|
103
|
+
value.tr("\r\n", ' ')
|
104
|
+
else
|
105
|
+
value
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Roqua::CsvExport
|
5
|
+
# Reads json files with export_version info and caches them.
|
6
|
+
class ExportVersions
|
7
|
+
def initialize(mapping_files_directory_path)
|
8
|
+
@base_dir = mapping_files_directory_path
|
9
|
+
@export_versions = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns column information for specified version for each variable in each questionnaire.
|
13
|
+
#
|
14
|
+
# Each column_hash looks like:
|
15
|
+
# {"key": "tot",
|
16
|
+
# "sub_key": "other",
|
17
|
+
# "header": "all_quests_tot_o",
|
18
|
+
# "source_type": "score"}
|
19
|
+
# Where header is the header within the csv file.
|
20
|
+
#
|
21
|
+
# @return [Hash] !{"fields" => {"oq45" => [{column_hash}, ...}}
|
22
|
+
def [](key)
|
23
|
+
@export_versions[key] ||= ::JSON.parse(File.read(File.join(@base_dir, "#{key}.json")))
|
24
|
+
end
|
25
|
+
|
26
|
+
def dig(key, *keys)
|
27
|
+
self[key].dig(*keys)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Array<String>] all the available versions, sorted oldest first.
|
31
|
+
def keys
|
32
|
+
Dir["#{@base_dir}/*.json"].map {|f| File.basename(f, File.extname(f)) }.sort
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns mapping for the questionnaire.
|
36
|
+
# First tries given export_version_key, but if the questonnaires wasn't defined then yet,
|
37
|
+
# it finds the first export_version that did define it.
|
38
|
+
# @return [Array<Hash>]
|
39
|
+
# @see []
|
40
|
+
def mapping_for(questionnaire_key, export_version_key)
|
41
|
+
dig(export_version_key, 'fields', questionnaire_key) \
|
42
|
+
|| keys.lazy
|
43
|
+
.reject { |key| key <= export_version_key }
|
44
|
+
.map { |key| dig(key, 'fields', questionnaire_key) }
|
45
|
+
.reject(&:nil?)
|
46
|
+
.first
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Roqua::CsvExport
|
4
|
+
# For each metadata key in export_versions, define a function to get the value for it for a given response.
|
5
|
+
module MetaData
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def anonymous(response)
|
9
|
+
response.anonymous ? 'anonymous' : ''
|
10
|
+
end
|
11
|
+
|
12
|
+
def birth_year(response)
|
13
|
+
nil # deprecated
|
14
|
+
end
|
15
|
+
|
16
|
+
def compl_by(response)
|
17
|
+
return nil unless response.completed_at
|
18
|
+
return nil if response.anonymous && response.entered_by&.external_identifier.nil?
|
19
|
+
|
20
|
+
response.entered_by&.external_identifier || response.dossier.external_identifier
|
21
|
+
end
|
22
|
+
|
23
|
+
def completed_at(response)
|
24
|
+
response.completed_at
|
25
|
+
end
|
26
|
+
|
27
|
+
def date(response)
|
28
|
+
response.observation_time
|
29
|
+
end
|
30
|
+
|
31
|
+
def emailed_at(response)
|
32
|
+
nil # deprecated
|
33
|
+
end
|
34
|
+
|
35
|
+
def gender(response)
|
36
|
+
nil #deprecated
|
37
|
+
end
|
38
|
+
|
39
|
+
def hide_pii_from_researchers(response)
|
40
|
+
response.hide_pii_from_researchers ? "hide" : "show"
|
41
|
+
end
|
42
|
+
|
43
|
+
def hide_values_from_professionals(response)
|
44
|
+
response.hide_values_from_professionals ? "hide" : "show"
|
45
|
+
end
|
46
|
+
|
47
|
+
def id(response)
|
48
|
+
response.id
|
49
|
+
end
|
50
|
+
|
51
|
+
def invited_at(response)
|
52
|
+
nil # deprecated
|
53
|
+
end
|
54
|
+
|
55
|
+
def location(response)
|
56
|
+
response.team&.name
|
57
|
+
end
|
58
|
+
|
59
|
+
def measurement(response)
|
60
|
+
response.measurement&.name
|
61
|
+
end
|
62
|
+
|
63
|
+
def non_response(response)
|
64
|
+
response.non_response&.id
|
65
|
+
end
|
66
|
+
|
67
|
+
def notes(response)
|
68
|
+
response.notes
|
69
|
+
end
|
70
|
+
|
71
|
+
def open_from(response)
|
72
|
+
response.open_from
|
73
|
+
end
|
74
|
+
|
75
|
+
def patient_id(response)
|
76
|
+
return nil if response.anonymous
|
77
|
+
|
78
|
+
response.dossier.external_identifier
|
79
|
+
end
|
80
|
+
|
81
|
+
def project(response)
|
82
|
+
nil # deprecated
|
83
|
+
end
|
84
|
+
|
85
|
+
def protocol(response)
|
86
|
+
response.measurement&.protocol&.name
|
87
|
+
end
|
88
|
+
|
89
|
+
def respondent_id(response)
|
90
|
+
return nil if response.anonymous
|
91
|
+
|
92
|
+
response.respondent&.id
|
93
|
+
end
|
94
|
+
|
95
|
+
def respondent_label(response)
|
96
|
+
response.respondent&.label || 'Medewerker'
|
97
|
+
end
|
98
|
+
|
99
|
+
def respondent_type(response)
|
100
|
+
response.respondent&.type || 'profess'
|
101
|
+
end
|
102
|
+
|
103
|
+
def roqua_id(response)
|
104
|
+
nil # deprecated
|
105
|
+
end
|
106
|
+
|
107
|
+
def started_at(response)
|
108
|
+
response.started_at
|
109
|
+
end
|
110
|
+
|
111
|
+
def variant(response)
|
112
|
+
response.questionnaire_variant
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Roqua
|
4
|
+
module CsvExport
|
5
|
+
module Models
|
6
|
+
extend ActiveSupport::Autoload
|
7
|
+
|
8
|
+
autoload :Dossier
|
9
|
+
autoload :Measurement
|
10
|
+
autoload :NonResponse
|
11
|
+
autoload :Professional
|
12
|
+
autoload :Protocol
|
13
|
+
autoload :Respondent
|
14
|
+
autoload :Response
|
15
|
+
autoload :ResponseFlag
|
16
|
+
autoload :ResponseTextvar
|
17
|
+
autoload :ResponseValue
|
18
|
+
autoload :ResponseScore
|
19
|
+
autoload :Team
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Roqua::CsvExport::Models
|
4
|
+
class Respondent < Sequel::Model
|
5
|
+
one_to_many :responses
|
6
|
+
|
7
|
+
def label
|
8
|
+
super.presence || default_label
|
9
|
+
end
|
10
|
+
|
11
|
+
def default_label
|
12
|
+
case type
|
13
|
+
when 'patient' then "Patiënt"
|
14
|
+
when 'parent' then "1e Ouder"
|
15
|
+
when 'second_parent' then "2e Ouder"
|
16
|
+
when 'teacher' then "Leraar"
|
17
|
+
when 'caregiver' then "Mantelzorger"
|
18
|
+
when 'profess' then "Medewerker"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Roqua::CsvExport::Models
|
4
|
+
class Response < Sequel::Model
|
5
|
+
many_to_one :dossier
|
6
|
+
many_to_one :measurement
|
7
|
+
many_to_one :questionnaire
|
8
|
+
many_to_one :team
|
9
|
+
many_to_one :entered_by, class: Professional
|
10
|
+
many_to_one :respondent
|
11
|
+
many_to_one :non_response
|
12
|
+
one_to_many :response_flags
|
13
|
+
one_to_many :response_scores
|
14
|
+
one_to_many :response_textvars
|
15
|
+
one_to_many :response_values
|
16
|
+
|
17
|
+
# List of answers to questions.
|
18
|
+
# @return [Hash{String=>String}] !{'v_1' => '3', ...}
|
19
|
+
def variable_hash
|
20
|
+
@variable_hash ||= response_values.each_with_object({}) do |response_value, hash|
|
21
|
+
hash[response_value.question_key] = response_value.data
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# List of calculated scores.
|
26
|
+
# @return [Hash{String=>Hash{String}}] !{'tot' => {'value' => '15', ...}, ...}
|
27
|
+
def score_hash
|
28
|
+
@response_score_hash ||= response_scores.each_with_object({}) do |response_score, hash|
|
29
|
+
(hash[response_score.score_key] ||= {})[response_score.score_subkey] = response_score.data
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Get answer belonging to given key.
|
34
|
+
# @param key [String] e.g. "v_1"
|
35
|
+
# @return [String] The value for specified question_key
|
36
|
+
def variable(key)
|
37
|
+
variable_hash[key]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Retrieve a score value. main value for a score will usually have sub_key "value".
|
41
|
+
# @param key [String] e.g. "tot"
|
42
|
+
# @param sub_key [String] e.g. "value" or "interpretation"
|
43
|
+
# @return [String]
|
44
|
+
def score(key, sub_key)
|
45
|
+
score_hash.dig(key, sub_key)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @param key [String] prepended with questionnaire_key
|
49
|
+
# @return [String]
|
50
|
+
def flag(key)
|
51
|
+
response_flags.find { |response_flag| response_flag.key == key }.value
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param key [String] prepended with questionnaire_key.
|
55
|
+
# @return [String]
|
56
|
+
def textvar(key)
|
57
|
+
response_textvars.find { |response_textvar| response_textvar.key == key }.value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
metadata
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: roqua-csv_export
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Henk van der Veen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-10-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sequel
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '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: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
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: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: yard
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '3.0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '3.0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: fabrication
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '2.9'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '2.9'
|
139
|
+
description: create csv exports from the sqlite export and the export_version json
|
140
|
+
email: henk.van.der.veen@gmail.com
|
141
|
+
executables: []
|
142
|
+
extensions: []
|
143
|
+
extra_rdoc_files: []
|
144
|
+
files:
|
145
|
+
- README.md
|
146
|
+
- Rakefile
|
147
|
+
- lib/roqua-csv_export.rb
|
148
|
+
- lib/roqua/csv_export.rb
|
149
|
+
- lib/roqua/csv_export/config.rb
|
150
|
+
- lib/roqua/csv_export/csv_export_questionnaire_version.rb
|
151
|
+
- lib/roqua/csv_export/export_versions.rb
|
152
|
+
- lib/roqua/csv_export/meta_data.rb
|
153
|
+
- lib/roqua/csv_export/models.rb
|
154
|
+
- lib/roqua/csv_export/models/dossier.rb
|
155
|
+
- lib/roqua/csv_export/models/measurement.rb
|
156
|
+
- lib/roqua/csv_export/models/non_response.rb
|
157
|
+
- lib/roqua/csv_export/models/professional.rb
|
158
|
+
- lib/roqua/csv_export/models/protocol.rb
|
159
|
+
- lib/roqua/csv_export/models/respondent.rb
|
160
|
+
- lib/roqua/csv_export/models/response.rb
|
161
|
+
- lib/roqua/csv_export/models/response_flag.rb
|
162
|
+
- lib/roqua/csv_export/models/response_score.rb
|
163
|
+
- lib/roqua/csv_export/models/response_textvar.rb
|
164
|
+
- lib/roqua/csv_export/models/response_value.rb
|
165
|
+
- lib/roqua/csv_export/models/team.rb
|
166
|
+
- lib/roqua/csv_export/version.rb
|
167
|
+
homepage: https://docs.roqua.net
|
168
|
+
licenses:
|
169
|
+
- MIT
|
170
|
+
metadata:
|
171
|
+
yard.run: yri
|
172
|
+
post_install_message:
|
173
|
+
rdoc_options: []
|
174
|
+
require_paths:
|
175
|
+
- lib
|
176
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ">="
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
requirements: []
|
187
|
+
rubygems_version: 3.0.3
|
188
|
+
signing_key:
|
189
|
+
specification_version: 4
|
190
|
+
summary: create csv exports from the sqlite export
|
191
|
+
test_files: []
|