quby-compiler 0.3.3 → 0.3.7
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/.ruby-version +1 -1
- data/CHANGELOG.md +18 -1
- data/Gemfile.lock +43 -43
- data/exe/quby-compile +2 -11
- data/lib/quby/compiler/dsl.rb +3 -3
- data/lib/quby/compiler/entities/outcome_table.rb +12 -0
- data/lib/quby/compiler/entities/questionnaire.rb +1 -3
- data/lib/quby/compiler/entities/questions/float_question.rb +9 -0
- data/lib/quby/compiler/entities/questions/integer_question.rb +9 -0
- data/lib/quby/compiler/entities/subscore_schema.rb +2 -1
- data/lib/quby/compiler/instance.rb +4 -4
- data/lib/quby/compiler/outputs/quby_frontend_v1_serializer.rb +0 -1
- data/lib/quby/compiler/outputs/roqua_serializer.rb +39 -2
- data/lib/quby/compiler/outputs/seed_serializer.rb +3 -7
- data/lib/quby/compiler/services/definition_validator.rb +22 -10
- data/lib/quby/compiler/services/quby_proxy.rb +2 -1
- data/lib/quby/compiler/version.rb +1 -1
- data/lib/quby/compiler.rb +1 -3
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9afe2a68ca9334f324a6d096918e625d432016b631794fdfe1db307acd25ebff
|
|
4
|
+
data.tar.gz: 87cce57c50f1509b48ef072d53dfa4f56a8880b3dc82c002dbd9c6b70a368c7b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 32acc8cd41565840352dc2c5b3137aca5f31422ee000424dd0b412d9ae9cadde00ff7d1eb5b92eb54b6b4ee493bd581413aee3c93fd01c2fd176fc57d7ec2e3b
|
|
7
|
+
data.tar.gz: 6f677f3ea56d37009e637298d58d1969761fa6793c412b42dc8068ca99bb47a185427d31beae7e29b60236ea724929e911ebafca78db2e0a2755babf9b1956bd
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.7.
|
|
1
|
+
2.7.2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
|
+
# 0.3.7
|
|
2
|
+
|
|
3
|
+
* Remove last_update
|
|
4
|
+
|
|
5
|
+
# 0.3.6
|
|
6
|
+
|
|
7
|
+
* `outcome_table` panel dsl method now exports the given outcome table definition to `roqua.json`
|
|
8
|
+
This can't be used in combination with the `outcome_table: ` attribute in score schemas.
|
|
9
|
+
|
|
10
|
+
# 0.3.5
|
|
11
|
+
|
|
12
|
+
* Allow score_schema's outcome_table to be set to nil to hide values from outcome tables
|
|
13
|
+
|
|
14
|
+
# 0.3.4
|
|
15
|
+
|
|
16
|
+
* Added preliminary support for sliders to the v2 output.
|
|
17
|
+
|
|
1
18
|
# 0.3.3
|
|
2
19
|
|
|
3
|
-
Replace `options={}` with `**options` in the builders to prevent prepare for ruby 3.0
|
|
20
|
+
* Replace `options={}` with `**options` in the builders to prevent prepare for ruby 3.0
|
|
4
21
|
|
|
5
22
|
# 0.3.2
|
|
6
23
|
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
quby-compiler (0.3.
|
|
4
|
+
quby-compiler (0.3.7)
|
|
5
5
|
actionview (>= 5.0)
|
|
6
6
|
activemodel (>= 5.0)
|
|
7
7
|
activesupport (>= 5.0)
|
|
@@ -15,86 +15,87 @@ PATH
|
|
|
15
15
|
GEM
|
|
16
16
|
remote: https://rubygems.org/
|
|
17
17
|
specs:
|
|
18
|
-
actionview (6.
|
|
19
|
-
activesupport (= 6.
|
|
18
|
+
actionview (6.1.4)
|
|
19
|
+
activesupport (= 6.1.4)
|
|
20
20
|
builder (~> 3.1)
|
|
21
21
|
erubi (~> 1.4)
|
|
22
22
|
rails-dom-testing (~> 2.0)
|
|
23
23
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
|
24
|
-
active_interaction (
|
|
25
|
-
activemodel (>=
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
active_interaction (4.0.6)
|
|
25
|
+
activemodel (>= 5, < 7)
|
|
26
|
+
activesupport (>= 5, < 7)
|
|
27
|
+
activemodel (6.1.4)
|
|
28
|
+
activesupport (= 6.1.4)
|
|
29
|
+
activerecord (6.1.4)
|
|
30
|
+
activemodel (= 6.1.4)
|
|
31
|
+
activesupport (= 6.1.4)
|
|
32
|
+
activesupport (6.1.4)
|
|
32
33
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
33
|
-
i18n (>=
|
|
34
|
-
minitest (
|
|
35
|
-
tzinfo (~>
|
|
36
|
-
zeitwerk (~> 2.
|
|
37
|
-
appsignal (
|
|
34
|
+
i18n (>= 1.6, < 2)
|
|
35
|
+
minitest (>= 5.1)
|
|
36
|
+
tzinfo (~> 2.0)
|
|
37
|
+
zeitwerk (~> 2.3)
|
|
38
|
+
appsignal (3.0.15)
|
|
38
39
|
rack
|
|
39
40
|
builder (3.2.4)
|
|
40
41
|
coderay (1.1.3)
|
|
41
|
-
concurrent-ruby (1.1.
|
|
42
|
+
concurrent-ruby (1.1.9)
|
|
42
43
|
crass (1.0.6)
|
|
43
44
|
diff-lcs (1.4.4)
|
|
44
|
-
dry-configurable (0.
|
|
45
|
+
dry-configurable (0.13.0)
|
|
45
46
|
concurrent-ruby (~> 1.0)
|
|
46
|
-
dry-core (~> 0.
|
|
47
|
-
dry-container (0.
|
|
47
|
+
dry-core (~> 0.6)
|
|
48
|
+
dry-container (0.9.0)
|
|
48
49
|
concurrent-ruby (~> 1.0)
|
|
49
|
-
dry-configurable (~> 0.
|
|
50
|
-
dry-core (0.
|
|
50
|
+
dry-configurable (~> 0.13, >= 0.13.0)
|
|
51
|
+
dry-core (0.7.1)
|
|
51
52
|
concurrent-ruby (~> 1.0)
|
|
52
|
-
dry-inflector (0.2.
|
|
53
|
-
dry-logic (1.
|
|
53
|
+
dry-inflector (0.2.1)
|
|
54
|
+
dry-logic (1.2.0)
|
|
54
55
|
concurrent-ruby (~> 1.0)
|
|
55
56
|
dry-core (~> 0.5, >= 0.5)
|
|
56
57
|
dry-struct (1.4.0)
|
|
57
58
|
dry-core (~> 0.5, >= 0.5)
|
|
58
59
|
dry-types (~> 1.5)
|
|
59
60
|
ice_nine (~> 0.11)
|
|
60
|
-
dry-types (1.5.
|
|
61
|
+
dry-types (1.5.1)
|
|
61
62
|
concurrent-ruby (~> 1.0)
|
|
62
63
|
dry-container (~> 0.3)
|
|
63
64
|
dry-core (~> 0.5, >= 0.5)
|
|
64
65
|
dry-inflector (~> 0.1, >= 0.1.2)
|
|
65
66
|
dry-logic (~> 1.0, >= 1.0.2)
|
|
66
67
|
erubi (1.10.0)
|
|
67
|
-
i18n (1.8.
|
|
68
|
+
i18n (1.8.10)
|
|
68
69
|
concurrent-ruby (~> 1.0)
|
|
69
70
|
ice_nine (0.11.2)
|
|
70
|
-
loofah (2.
|
|
71
|
+
loofah (2.12.0)
|
|
71
72
|
crass (~> 1.0.2)
|
|
72
73
|
nokogiri (>= 1.5.9)
|
|
73
74
|
method_source (1.0.0)
|
|
74
|
-
mini_portile2 (2.
|
|
75
|
+
mini_portile2 (2.6.1)
|
|
75
76
|
minitest (5.14.4)
|
|
76
77
|
naught (1.1.0)
|
|
77
|
-
nokogiri (1.
|
|
78
|
-
mini_portile2 (~> 2.
|
|
78
|
+
nokogiri (1.12.5)
|
|
79
|
+
mini_portile2 (~> 2.6.1)
|
|
79
80
|
racc (~> 1.4)
|
|
80
|
-
nokogumbo (2.0.
|
|
81
|
+
nokogumbo (2.0.5)
|
|
81
82
|
nokogiri (~> 1.8, >= 1.8.4)
|
|
82
83
|
pry (0.13.1)
|
|
83
84
|
coderay (~> 1.1)
|
|
84
85
|
method_source (~> 1.0)
|
|
85
|
-
racc (1.
|
|
86
|
+
racc (1.6.0)
|
|
86
87
|
rack (2.2.3)
|
|
87
88
|
rails-dom-testing (2.0.3)
|
|
88
89
|
activesupport (>= 4.2.0)
|
|
89
90
|
nokogiri (>= 1.6)
|
|
90
|
-
rails-html-sanitizer (1.
|
|
91
|
+
rails-html-sanitizer (1.4.2)
|
|
91
92
|
loofah (~> 2.3)
|
|
92
93
|
rake (12.3.3)
|
|
93
|
-
redcarpet (3.5.
|
|
94
|
-
roqua-support (0.
|
|
95
|
-
active_interaction (
|
|
96
|
-
activesupport (>= 5.
|
|
97
|
-
appsignal (>= 2.9, <
|
|
94
|
+
redcarpet (3.5.1)
|
|
95
|
+
roqua-support (0.4.1)
|
|
96
|
+
active_interaction (>= 3.0, < 5.0)
|
|
97
|
+
activesupport (>= 5.2, < 6.2)
|
|
98
|
+
appsignal (>= 2.9, < 3.1)
|
|
98
99
|
naught (~> 1.0)
|
|
99
100
|
with_advisory_lock (~> 3.2)
|
|
100
101
|
rspec (3.9.0)
|
|
@@ -110,12 +111,11 @@ GEM
|
|
|
110
111
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
111
112
|
rspec-support (~> 3.9.0)
|
|
112
113
|
rspec-support (3.9.3)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
thread_safe (~> 0.1)
|
|
114
|
+
tzinfo (2.0.4)
|
|
115
|
+
concurrent-ruby (~> 1.0)
|
|
116
116
|
with_advisory_lock (3.2.0)
|
|
117
117
|
activerecord (>= 3.2)
|
|
118
|
-
zeitwerk (2.
|
|
118
|
+
zeitwerk (2.5.1)
|
|
119
119
|
|
|
120
120
|
PLATFORMS
|
|
121
121
|
ruby
|
|
@@ -127,4 +127,4 @@ DEPENDENCIES
|
|
|
127
127
|
rspec (~> 3.0)
|
|
128
128
|
|
|
129
129
|
BUNDLED WITH
|
|
130
|
-
2.
|
|
130
|
+
2.2.15
|
data/exe/quby-compile
CHANGED
|
@@ -8,7 +8,6 @@ require "quby/compiler"
|
|
|
8
8
|
|
|
9
9
|
output_path = "output"
|
|
10
10
|
lookup_tables_path = "lookup_tables"
|
|
11
|
-
seeds_path = "seeds"
|
|
12
11
|
|
|
13
12
|
OptionParser.new do |opts|
|
|
14
13
|
opts.banner = "Usage: quby-compile FILE_OR_DIRS [options]"
|
|
@@ -19,10 +18,6 @@ OptionParser.new do |opts|
|
|
|
19
18
|
opts.on("--lookup-tables=INPUT") do |value|
|
|
20
19
|
lookup_tables_path = value
|
|
21
20
|
end
|
|
22
|
-
|
|
23
|
-
opts.on("--seeds=INPUT") do |value|
|
|
24
|
-
seeds_path = value
|
|
25
|
-
end
|
|
26
21
|
end.parse!
|
|
27
22
|
|
|
28
23
|
paths = ARGV.flat_map do |file_or_dir|
|
|
@@ -38,15 +33,11 @@ lookup_tables = Quby::Compiler::Entities::LookupTables.new(lookup_tables_path)
|
|
|
38
33
|
paths.each do |path|
|
|
39
34
|
puts "Compiling #{path}"
|
|
40
35
|
|
|
41
|
-
key = File.basename(
|
|
36
|
+
key = File.basename(File.dirname(path))
|
|
42
37
|
sourcecode = File.read(path)
|
|
43
|
-
|
|
44
|
-
seed_path = File.join(seeds_path, "#{key}.yml")
|
|
45
|
-
seeds = File.exist?(seed_path) ? YAML.load(File.read(seed_path)) : nil
|
|
46
|
-
compiled = Quby::Compiler.compile(key, sourcecode, path: path, seeds: seeds, lookup_tables: lookup_tables, last_update: last_update)
|
|
38
|
+
compiled = Quby::Compiler.compile(key, sourcecode, path: path, lookup_tables: lookup_tables)
|
|
47
39
|
|
|
48
40
|
FileUtils.mkdir_p(File.join(output_path, key))
|
|
49
|
-
|
|
50
41
|
compiled[:outputs].each do |type, output|
|
|
51
42
|
next unless output
|
|
52
43
|
File.open(File.join(output_path, key, output.filename), 'w') do |file|
|
data/lib/quby/compiler/dsl.rb
CHANGED
|
@@ -9,15 +9,15 @@ module Quby
|
|
|
9
9
|
module Compiler
|
|
10
10
|
module DSL
|
|
11
11
|
def self.build_from_definition(definition)
|
|
12
|
-
Entities::Questionnaire.new(definition.key
|
|
12
|
+
Entities::Questionnaire.new(definition.key).tap do |questionnaire|
|
|
13
13
|
builder = QuestionnaireBuilder.new(questionnaire, lookup_tables: definition.lookup_tables)
|
|
14
14
|
builder.instance_eval(definition.sourcecode, definition.path) if definition.sourcecode
|
|
15
15
|
questionnaire.callback_after_dsl_enhance_on_questions
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def self.build(key, sourcecode = nil, path: nil,
|
|
20
|
-
Entities::Questionnaire.new(key
|
|
19
|
+
def self.build(key, sourcecode = nil, path: nil, lookup_tables: {}, &block)
|
|
20
|
+
Entities::Questionnaire.new(key).tap do |questionnaire|
|
|
21
21
|
builder = QuestionnaireBuilder.new(questionnaire, lookup_tables: lookup_tables)
|
|
22
22
|
builder.instance_eval(sourcecode, path || key) if sourcecode
|
|
23
23
|
builder.instance_eval(&block) if block
|
|
@@ -15,6 +15,7 @@ module Quby
|
|
|
15
15
|
validates :score_keys, :subscore_keys, :questionnaire, :key, presence: true
|
|
16
16
|
validates :name, presence: true, if: proc { |table| table.default_collapsed }
|
|
17
17
|
validate :references_existing_score_keys
|
|
18
|
+
validate :no_outcome_tables_defined_in_score_schemas
|
|
18
19
|
|
|
19
20
|
def references_existing_score_keys
|
|
20
21
|
(score_keys - questionnaire.score_schemas.values.map(&:key)).each do |missing_key|
|
|
@@ -25,6 +26,17 @@ module Quby
|
|
|
25
26
|
errors.add :subscore_keys, "#{missing_key.inspect} not found in subscore schemas"
|
|
26
27
|
end
|
|
27
28
|
end
|
|
29
|
+
|
|
30
|
+
def no_outcome_tables_defined_in_score_schemas
|
|
31
|
+
if questionnaire.score_schemas.values.any? do |schema|
|
|
32
|
+
schema.subscore_schemas.any? do |subscore|
|
|
33
|
+
subscore.outcome_table != :main
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
errors.add :score_schemas,
|
|
37
|
+
"Outcome table associations defined in score schemas should not be combined with explicit outcome tables"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
28
40
|
end
|
|
29
41
|
end
|
|
30
42
|
end
|
|
@@ -29,10 +29,9 @@ module Quby
|
|
|
29
29
|
|
|
30
30
|
RESPONDENT_TYPES = %i( profess patient parent second_parent teacher caregiver )
|
|
31
31
|
|
|
32
|
-
def initialize(key
|
|
32
|
+
def initialize(key)
|
|
33
33
|
@key = key
|
|
34
34
|
@sbg_domains = []
|
|
35
|
-
@last_update = Time.at(last_update.to_i)
|
|
36
35
|
@score_calculations = {}.with_indifferent_access
|
|
37
36
|
@charts = Charting::Charts.new
|
|
38
37
|
@fields = Fields.new(self)
|
|
@@ -92,7 +91,6 @@ module Quby
|
|
|
92
91
|
|
|
93
92
|
attr_accessor :last_author
|
|
94
93
|
attr_accessor :allow_hotkeys # allow hotkeys for :all views, just :bulk views (default), or :none for never
|
|
95
|
-
attr_accessor :last_update
|
|
96
94
|
|
|
97
95
|
attr_accessor :charts
|
|
98
96
|
|
|
@@ -5,6 +5,15 @@ module Quby
|
|
|
5
5
|
module Entities
|
|
6
6
|
module Questions
|
|
7
7
|
class FloatQuestion < Question
|
|
8
|
+
def as_json(options = {})
|
|
9
|
+
super.merge(
|
|
10
|
+
minimum: minimum,
|
|
11
|
+
maximum: maximum,
|
|
12
|
+
step: 0.01, # fixed in v1.
|
|
13
|
+
# defaultPosition: default_position # Needs discussion, can be number or string "hidden"
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
8
17
|
def size
|
|
9
18
|
@size || 30
|
|
10
19
|
end
|
|
@@ -5,6 +5,15 @@ module Quby
|
|
|
5
5
|
module Entities
|
|
6
6
|
module Questions
|
|
7
7
|
class IntegerQuestion < Question
|
|
8
|
+
def as_json(options = {})
|
|
9
|
+
super.merge(
|
|
10
|
+
minimum: minimum,
|
|
11
|
+
maximum: maximum,
|
|
12
|
+
step: 1, # fixed in v1.
|
|
13
|
+
# defaultPosition: default_position # Needs discussion, can be number or string "hidden"
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
8
17
|
def size
|
|
9
18
|
@size || 30
|
|
10
19
|
end
|
|
@@ -16,7 +16,8 @@ module Quby
|
|
|
16
16
|
attribute :calculation_key?, Types::Symbol
|
|
17
17
|
# [Optional argument] The name of the outcome table where this subscore should be shown. Used for cases where scores
|
|
18
18
|
# differ in subscores too much to be shown as one table. By default, all scores end up in the `:main` table.
|
|
19
|
-
|
|
19
|
+
# When outcome_table is explicitly nil, the value should not be shown in outcome tables
|
|
20
|
+
attribute :outcome_table, Types::Symbol.optional.default(:main)
|
|
20
21
|
end
|
|
21
22
|
end
|
|
22
23
|
end
|
|
@@ -7,12 +7,12 @@ module Quby
|
|
|
7
7
|
@lookup_tables = lookup_tables
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def compile(key:, sourcecode:,
|
|
10
|
+
def compile(key:, sourcecode:, path: nil, &block)
|
|
11
11
|
if block # defined in block for tests
|
|
12
12
|
questionnaire = DSL.build(key, path: path, &block)
|
|
13
13
|
else # sourcecode given as string
|
|
14
|
-
tempfile = Tempfile.new(key)
|
|
15
|
-
questionnaire = Entities::Questionnaire.new(key
|
|
14
|
+
tempfile = Tempfile.new([key, '.rb'])
|
|
15
|
+
questionnaire = Entities::Questionnaire.new(key)
|
|
16
16
|
Thread.current["quby-questionnaire-loading"] = Quby::Compiler::DSL::QuestionnaireBuilder.new(questionnaire, lookup_tables: lookup_tables)
|
|
17
17
|
|
|
18
18
|
tempfile.puts "Thread.current['quby-questionnaire-loading'].instance_eval do"
|
|
@@ -41,7 +41,7 @@ module Quby
|
|
|
41
41
|
seeds: Output.new(
|
|
42
42
|
key: :seeds,
|
|
43
43
|
filename: "seeds.yml",
|
|
44
|
-
content: YAML.dump(Outputs::SeedSerializer.new(questionnaire
|
|
44
|
+
content: YAML.dump(Outputs::SeedSerializer.new(questionnaire).generate),
|
|
45
45
|
),
|
|
46
46
|
quby_frontend_v1: Output.new(
|
|
47
47
|
key: :quby_frontend_v1,
|
|
@@ -322,7 +322,6 @@ module Quby
|
|
|
322
322
|
licensor: questionnaire.licensor,
|
|
323
323
|
language: questionnaire.language,
|
|
324
324
|
renderer_version: questionnaire.renderer_version,
|
|
325
|
-
last_update: questionnaire.last_update,
|
|
326
325
|
last_author: questionnaire.last_author,
|
|
327
326
|
extra_css: questionnaire.extra_css,
|
|
328
327
|
allow_switch_to_bulk: questionnaire.allow_switch_to_bulk,
|
|
@@ -84,19 +84,56 @@ module Quby
|
|
|
84
84
|
# <subscore_key:Symbol>: <subscore.label:String> # headers for each subscore key for all tables.
|
|
85
85
|
|
|
86
86
|
def outcome_tables_schema
|
|
87
|
+
if questionnaire.outcome_tables.present?
|
|
88
|
+
outcome_tables_from_definition
|
|
89
|
+
else
|
|
90
|
+
outcome_tables_from_score_schemas
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def outcome_tables_from_definition
|
|
95
|
+
# hash of tables, with the score keys (rows) and subscore keys (columns) used for each
|
|
96
|
+
tables = {}
|
|
97
|
+
# hash of `subscore_key: subscore_label` pairs used in tables
|
|
98
|
+
headers = {}
|
|
99
|
+
|
|
100
|
+
questionnaire.outcome_tables.each do |table|
|
|
101
|
+
tables[table.key] = {name: table.name,
|
|
102
|
+
default_collapsed: table.default_collapsed,
|
|
103
|
+
score_keys: table.score_keys,
|
|
104
|
+
subscore_keys: table.subscore_keys}.compact
|
|
105
|
+
|
|
106
|
+
table.subscore_keys.each do |subscore_key|
|
|
107
|
+
table.score_keys.find do |score_key|
|
|
108
|
+
subschema = questionnaire.score_schemas[score_key].subscore_schemas.find do |subschema|
|
|
109
|
+
subschema.key == subscore_key
|
|
110
|
+
end
|
|
111
|
+
headers[subscore_key] = subschema&.label
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
{
|
|
117
|
+
headers: headers,
|
|
118
|
+
tables: tables,
|
|
119
|
+
}
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def outcome_tables_from_score_schemas
|
|
87
123
|
# hash of tables, with the score keys (rows) and subscore keys (columns) used for each
|
|
88
124
|
tables = Hash.new{ |hash, key| hash[key] = {score_keys: Set.new, subscore_keys: Set.new } }
|
|
89
125
|
# hash of `subscore_key: subscore_label` pairs used in tables
|
|
90
126
|
headers = {}
|
|
91
|
-
|
|
127
|
+
|
|
92
128
|
questionnaire.score_schemas.values.each do |schema|
|
|
93
129
|
schema.subscore_schemas.each do |subschema|
|
|
130
|
+
next if subschema.outcome_table.blank?
|
|
94
131
|
tables[subschema.outcome_table][:subscore_keys] << subschema.key
|
|
95
132
|
tables[subschema.outcome_table][:score_keys] << schema.key
|
|
96
133
|
headers[subschema.key] = subschema.label
|
|
97
134
|
end
|
|
98
135
|
end
|
|
99
|
-
|
|
136
|
+
|
|
100
137
|
{
|
|
101
138
|
headers: headers,
|
|
102
139
|
tables: tables,
|
|
@@ -7,23 +7,19 @@ module Quby
|
|
|
7
7
|
attr_reader :questionnaire
|
|
8
8
|
attr_reader :seeds
|
|
9
9
|
|
|
10
|
-
def initialize(questionnaire
|
|
10
|
+
def initialize(questionnaire)
|
|
11
11
|
@questionnaire = questionnaire
|
|
12
12
|
@seeds = seeds || []
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def generate
|
|
16
|
-
roqua_keys
|
|
17
|
-
|
|
18
|
-
roqua_keys.map do |roqua_key|
|
|
19
|
-
seed = seeds.find { |seed| seed["key"] == roqua_key } || {}
|
|
20
|
-
|
|
16
|
+
questionnaire.roqua_keys.map do |roqua_key|
|
|
21
17
|
new_seed = Services::QubyProxy.new(
|
|
22
18
|
questionnaire,
|
|
23
19
|
quby_key: questionnaire.key,
|
|
24
20
|
roqua_key: roqua_key,
|
|
25
21
|
skip_score_keys_consistency_check: true
|
|
26
|
-
).generate
|
|
22
|
+
).generate
|
|
27
23
|
|
|
28
24
|
Services::SeedDiff.new.apply_patch(new_seed, questionnaire.seeds_patch[roqua_key])
|
|
29
25
|
end
|
|
@@ -15,8 +15,8 @@ module Quby
|
|
|
15
15
|
|
|
16
16
|
def validate(definition)
|
|
17
17
|
questionnaire = DSL.build_from_definition(definition)
|
|
18
|
+
validate_metadata(questionnaire)
|
|
18
19
|
validate_fields(questionnaire)
|
|
19
|
-
validate_title(questionnaire)
|
|
20
20
|
validate_questions(questionnaire)
|
|
21
21
|
validate_scores(questionnaire)
|
|
22
22
|
validate_table_edgecases(questionnaire)
|
|
@@ -25,7 +25,6 @@ module Quby
|
|
|
25
25
|
validate_outcome_tables(questionnaire)
|
|
26
26
|
validate_markdown_fields(questionnaire) if questionnaire.validate_html
|
|
27
27
|
validate_raw_content_items(questionnaire) if questionnaire.validate_html
|
|
28
|
-
validate_scores(questionnaire)
|
|
29
28
|
# Some compilation errors are Exceptions (pure syntax errors) and some StandardErrors (NameErrors)
|
|
30
29
|
rescue Exception => exception # rubocop:disable Lint/RescueException
|
|
31
30
|
definition.errors.add(:sourcecode, {message: "Questionnaire error: #{definition.key}\n" \
|
|
@@ -33,6 +32,20 @@ module Quby
|
|
|
33
32
|
backtrace: exception.backtrace[0..20]})
|
|
34
33
|
end
|
|
35
34
|
|
|
35
|
+
def validate_metadata(questionnaire)
|
|
36
|
+
if questionnaire.title.blank?
|
|
37
|
+
fail "Questionnaire title is missing."
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if questionnaire.short_description && questionnaire.short_description.size > 255
|
|
41
|
+
fail "Questionnaire short_description is too long."
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
if questionnaire.description && questionnaire.description.size > 255
|
|
45
|
+
fail "Questionnaire description is too long."
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
36
49
|
def validate_fields(questionnaire)
|
|
37
50
|
questionnaire.fields.input_keys
|
|
38
51
|
.find { |k| !k.is_a?(Symbol) }
|
|
@@ -42,12 +55,6 @@ module Quby
|
|
|
42
55
|
&.tap { |k| fail "Answer key #{k} is not a symbol" }
|
|
43
56
|
end
|
|
44
57
|
|
|
45
|
-
def validate_title(questionnaire)
|
|
46
|
-
if questionnaire.title.blank?
|
|
47
|
-
fail "Questionnaire title is missing."
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
58
|
def validate_questions(questionnaire)
|
|
52
59
|
questionnaire.answer_keys.each do |key|
|
|
53
60
|
validate_key_format(key)
|
|
@@ -81,6 +88,13 @@ module Quby
|
|
|
81
88
|
fail "Score #{score.key} does not have a score schema" unless score_schema
|
|
82
89
|
fail "Score label langer dan 100 tekens (geeft problemen oru accare)\n #{score_schema.label}" if score_schema.label&.length > 100
|
|
83
90
|
end
|
|
91
|
+
|
|
92
|
+
export_keys = questionnaire.score_schemas.flat_map { |_key, score_schema|
|
|
93
|
+
score_schema.subscore_schemas.map(&:export_key)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
duplicate_export_keys = export_keys.tally.select { |key, count| count > 1 }.keys
|
|
97
|
+
fail "Score export keys not unique, duplicates: #{duplicate_export_keys}" if duplicate_export_keys.present?
|
|
84
98
|
end
|
|
85
99
|
|
|
86
100
|
def validate_question_options(questionnaire, question)
|
|
@@ -241,8 +255,6 @@ scores_schema tables to the resulting seed."
|
|
|
241
255
|
|
|
242
256
|
def validate_score_label_present(score)
|
|
243
257
|
fail "Score #{score.key} label must be passed in as an option." unless score.label.present?
|
|
244
|
-
|
|
245
|
-
|
|
246
258
|
end
|
|
247
259
|
|
|
248
260
|
def validate_subquestion_absence_in_select(question)
|
data/lib/quby/compiler.rb
CHANGED
|
@@ -29,13 +29,11 @@ require 'quby/compiler/outputs'
|
|
|
29
29
|
|
|
30
30
|
module Quby
|
|
31
31
|
module Compiler
|
|
32
|
-
def self.compile(key, sourcecode, path: nil,
|
|
32
|
+
def self.compile(key, sourcecode, path: nil, lookup_tables:, &block)
|
|
33
33
|
Quby::Compiler::Instance.new(lookup_tables: lookup_tables).compile(
|
|
34
34
|
key: key,
|
|
35
35
|
sourcecode: sourcecode,
|
|
36
36
|
path: path,
|
|
37
|
-
seeds: seeds,
|
|
38
|
-
last_update: last_update,
|
|
39
37
|
&block
|
|
40
38
|
)
|
|
41
39
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: quby-compiler
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Marten Veldthuis
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-11-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activemodel
|
|
@@ -271,7 +271,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
271
271
|
- !ruby/object:Gem::Version
|
|
272
272
|
version: '0'
|
|
273
273
|
requirements: []
|
|
274
|
-
rubygems_version: 3.
|
|
274
|
+
rubygems_version: 3.2.15
|
|
275
275
|
signing_key:
|
|
276
276
|
specification_version: 4
|
|
277
277
|
summary: Quby::Compiler compiles a DSL for questionnaires to JSON
|