quby 5.0.0.pre2 → 5.0.0.pre3

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: 4d19ac693a1e2e0530ead24bd6154f8fb6bd29b7d12cac079cd605d3b79329ec
4
- data.tar.gz: d73d97a84f5b8d3fefd5655d3dc6663a069f4519c42f4cef3121b955630480f1
3
+ metadata.gz: 2ff840130087f113cabb79c809f8046fd434993e436da3efedcc397597c43979
4
+ data.tar.gz: f8b6977b5802b86e676d06fa13771a70919acab2538dbfbfe8a2a5808211da78
5
5
  SHA512:
6
- metadata.gz: a9e02fcd7b0116a1c38a34b611a8e460cfa052f83b6b977bfcf67ffb8a1851ac15b2394294266bc97da6892fd9f96edc105312a021dd708dffca8c23aa76d272
7
- data.tar.gz: 8cf3fb6290472a64a730747bd2b5824a952d012c679645d1ddc907754677e94c2dce93ee8b6892d8f4decc1ce13c81a3cba5debd05a8d7afaac3db292d15f832
6
+ metadata.gz: 178d14bdac8b8fd8b2ac1e45cb6dfdd8b22c2d5270d51a832c6c01e5eb1207e4ad498a448ddb2908c55f029c6d9db35e1c507f473548112c72bfa45deb25a56e
7
+ data.tar.gz: c7ea63e6170b68d8b0fc48340a9f5db3333908e9fb08086a0557670b89c77e50f4010565692038f7acc8c5c53a03e312c3fdc8416a5515f28c5b157056b3b9c0
@@ -27,7 +27,6 @@ and where it can store its answers.
27
27
  ```ruby
28
28
  Quby.questionnaire_repo = Quby::Questionnaires::Repos::DiskRepo.new(Rails.root.join("db/questionnaires/definitions"))
29
29
  Quby.answer_repo = Quby::Answers::Repos::MongoidRepo.new
30
- Quby.lookup_table_repo = Quby::LookupTableRepo::Disk.new(Rails.root.join("db/questionnaires/lookup_tables"))
31
30
  Quby::Settings.shared_secret = ENV["QUBY_SHARED_SECRET"]
32
31
  ```
33
32
 
@@ -38,14 +38,6 @@ module Quby
38
38
  @questionnaires_api = nil
39
39
  end
40
40
 
41
- def lookup_table_repo=(repo)
42
- @lookup_table_repo = repo
43
- end
44
-
45
- def lookup_table_repo
46
- @lookup_table_repo || fail("Quby does not have its lookup table repo (Quby.lookup_table_repo) configured.")
47
- end
48
-
49
41
  def fixtures_path
50
42
  File.expand_path File.join('..', '..', 'spec', 'fixtures'), __FILE__
51
43
  end
@@ -79,7 +71,7 @@ module Quby
79
71
  end
80
72
 
81
73
  require 'quby/settings'
74
+ require 'quby/table_backend/range_tree'
82
75
  require 'quby/questionnaires'
83
76
  require 'quby/answers'
84
- require 'quby/engine'
85
- require 'quby/lookup_table_repo'
77
+ require 'quby/engine'
@@ -82,7 +82,7 @@ module Quby
82
82
  attr_accessor :extra_question_values
83
83
  attr_accessor :extra_failed_validations
84
84
 
85
- def initialize(_id: nil, questionnaire_id: nil, questionnaire_key: nil,
85
+ def initialize(_id: nil, questionnaire_id: nil, questionnaire_key: nil, questionnaire: nil,
86
86
  raw_params: nil, value: nil, patient_id: nil, patient: nil,
87
87
  token: nil, active: true, test: false, created_at: nil, updated_at: nil,
88
88
  started_at: nil, completed_at: nil, outcome: nil, outcome_generated_at: nil,
@@ -111,6 +111,8 @@ module Quby
111
111
  self.import_notes = import_notes || {}
112
112
  self.flags = flags
113
113
  self.textvars = textvars
114
+
115
+ @questionnaire = questionnaire
114
116
  end
115
117
 
116
118
  def id
@@ -162,7 +164,7 @@ module Quby
162
164
 
163
165
  # Faux belongs_to :questionnaire
164
166
  def questionnaire
165
- Quby.questionnaires.find(questionnaire_key)
167
+ @questionnaire ||= Quby.questionnaires.find(questionnaire_key)
166
168
  end
167
169
 
168
170
  def mark_completed(start_time)
@@ -231,9 +231,7 @@ module Quby
231
231
  end
232
232
 
233
233
  def table_lookup(table_key, parameters)
234
- @questionnaire.lookup_tables[table_key] ||= Quby::LookupTable.new table_key
235
- @questionnaire.lookup_tables[table_key] \
236
- .lookup(parameters)
234
+ @questionnaire.lookup_tables.fetch(table_key).lookup(parameters)
237
235
  end
238
236
 
239
237
  # Public: Ensure given question_keys have answers. Strings with nothing but whitespace are
@@ -15,7 +15,6 @@ require 'jquery-ui-rails'
15
15
  require 'compass-blueprint'
16
16
 
17
17
  require 'susy'
18
- require 'quby/lookup_table'
19
18
  require 'quby/range_categories'
20
19
  require 'quby/pdf_renderer'
21
20
 
@@ -3,14 +3,16 @@
3
3
  module Quby
4
4
  module Questionnaires
5
5
  module DSL
6
+ # Deprecated, precompile elsewhere and use from_json
6
7
  def self.build_from_definition(definition)
7
- compiled = Quby::Compiler.compile(definition.key, definition.sourcecode, seeds: [], path: definition.path)
8
+ compiled = Quby::Compiler.compile(definition.key, definition.sourcecode, seeds: [], lookup_tables: {}, path: definition.path)
8
9
  data = JSON.parse(compiled[:outputs][:quby_frontend_v1].content)
9
10
  Deserializer.from_json(data)
10
11
  end
11
12
 
13
+ # Deprecated, precompile elsewhere and use from_json
12
14
  def self.build(key, sourcecode = nil, timestamp: nil, &block)
13
- compiled = Quby::Compiler.compile(key, sourcecode, seeds: [], &block)
15
+ compiled = Quby::Compiler.compile(key, sourcecode, seeds: [], lookup_tables: {}, &block)
14
16
  data = JSON.parse(compiled[:outputs][:quby_frontend_v1].content)
15
17
  Deserializer.from_json(data)
16
18
  end
@@ -2,8 +2,6 @@
2
2
 
3
3
  # A lookup tree to find values by multiple arguments.
4
4
  #
5
- # Created by LookupTable from a csv file or by add_lookup_tree from dsl.
6
- #
7
5
  # Example tree:
8
6
  # Inhibitie:
9
7
  # male:
@@ -36,27 +34,6 @@ module Quby::TableBackend
36
34
  @tree = tree
37
35
  end
38
36
 
39
- # load csv data into a tree.
40
- # each row is a path through the tree.
41
- # String and float types are used to make an exact match.
42
- # A range is always a range between two floats where the range is between
43
- # the low value (inclusive) and the high value (exclusive),
44
- # written as 4:5 (low:high). These boundaries can be given as floats or
45
- # integers, but internally they are always treated as a floats.
46
- # The low and high values of a range cannot be equal.
47
- # Use minfinity or infinity to create infinite ranges.
48
- #
49
- # @params levels [Array<String>] An array of column names
50
- # @param compare [Array<String>]An array of lookup types (string, float or range) for each column
51
- # @param data [Array<Array<>>] The rows describing a path through the tree.
52
- def self.from_csv(levels:, compare:, data:)
53
- tree = data.each_with_object({}) do |row, tree|
54
- add_to_tree(tree, row, levels, compare)
55
- end
56
- new(levels: levels, tree: tree)
57
- end
58
-
59
-
60
37
  # Given a parameters hash that contains a value or range for every
61
38
  # level in the tree, find and return the normscore.
62
39
  # ie. `lookup({age: 10, raw: 5, scale: 'Inhibitie', gender: 'male'})` => 39
@@ -67,34 +44,6 @@ module Quby::TableBackend
67
44
 
68
45
  private
69
46
 
70
- def self.add_to_tree(tree, (value, *path), (level, *levels), (compare, *compares))
71
- key = case compare
72
- when 'string' then value.to_s
73
- when 'float' then parse_float(value)
74
- when 'range' then create_range(value)
75
- end
76
-
77
- if levels.empty?
78
- return key
79
- end
80
-
81
- tree.merge! key => add_to_tree(tree[key] || {}, path, levels, compares)
82
- end
83
-
84
- def self.create_range(value)
85
- min, max = value.split(':').map { |val| parse_float(val) }
86
- fail 'Cannot create range between two equal values' if min == max
87
- (min...max)
88
- end
89
-
90
- def self.parse_float(value)
91
- case value
92
- when 'infinity' then Float::INFINITY
93
- when 'minfinity' then -Float::INFINITY
94
- else Float(value)
95
- end
96
- end
97
-
98
47
  # All parameters must be present to do a lookup but the order does not matter.
99
48
  def validate_parameters(parameters)
100
49
  if @levels[0...-1].sort != parameters.keys.map(&:to_s).sort
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quby
4
- VERSION = "5.0.0.pre2"
4
+ VERSION = "5.0.0.pre3"
5
5
  end
@@ -485,26 +485,16 @@ module Quby::Answers::Services
485
485
  let(:calculator) { ScoreCalculator.new(questionnaire: questionnaire, values: {}, timestamp: timestamp) }
486
486
  let(:table_double) { double.as_null_object }
487
487
 
488
- before do
489
- allow(Quby::LookupTable).to receive(:new).and_return(table_double)
490
- end
491
-
492
- it 'instantiates a new Quby::Answers::Entities::LookupTable if the table_hash cache does not know the key' do
488
+ it 'raises an error if lookup table cannot be found' do
493
489
  expect(questionnaire.lookup_tables).to be_empty
494
- calculator.table_lookup :test_table, score: 1
495
- expect(questionnaire.lookup_tables[:test_table]).to be(table_double)
496
- end
497
-
498
- it 'uses the memoized lookuptable if there is a cache hit' do
499
- calculator.table_lookup :test_table, score: 1
500
- expect(table_double).to receive(:lookup)
501
- calculator.table_lookup :test_table, score: 1
490
+ expect { calculator.table_lookup :test_table, score: 1 }.to raise_error(KeyError)
502
491
  end
503
492
 
504
493
  it 'looks up the given parameters on the given table' do
494
+ questionnaire.lookup_tables[:test_table] = table_double
505
495
  parameters = {score: 1}
506
- expect(table_double).to receive(:lookup).with parameters
507
496
  calculator.table_lookup :test_table, parameters
497
+ expect(table_double).to have_received(:lookup).with parameters
508
498
  end
509
499
 
510
500
  context 'with add_lookup_tree inside dsl' do
@@ -1,17 +1,22 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Quby::TableBackend::RangeTree do
4
- let(:csv_key) { 'test' }
5
- let(:data) { Quby.lookup_table_repo.retrieve(csv_key) }
6
- let(:tree) { described_class.from_csv(levels: data.shift, compare: data.shift, data: data) }
7
-
8
- describe '#from_csv' do
9
- context 'invalid csv data' do
10
- let(:csv_key) { 'bad_range' }
11
- it 'fails when csv data contains a range between two equal values' do
12
- expect { tree }.to raise_error(RuntimeError, 'Cannot create range between two equal values')
13
- end
14
- end
4
+ let(:tree) do
5
+ described_class.new(
6
+ levels: ["scale", "gender", "age", "raw", "norm"],
7
+ tree: {
8
+ "Inhibitie" => {
9
+ "male" => {
10
+ (10.0...11.0) => {
11
+ (-Float::INFINITY...10.0) => 39.0,
12
+ (10.0...20.0) => 42.0,
13
+ (20.0...30.0) => 71.0,
14
+ (30.0...Float::INFINITY) => 75.0
15
+ }
16
+ }
17
+ }
18
+ }
19
+ )
15
20
  end
16
21
 
17
22
  describe '#lookup' do
@@ -68,7 +73,23 @@ describe Quby::TableBackend::RangeTree do
68
73
  end
69
74
 
70
75
  describe 'definition containing range with float values' do
71
- let(:csv_key) { 'float_test' }
76
+ let(:tree) do
77
+ described_class.new(
78
+ levels: ["scale", "gender", "age", "raw", "norm"],
79
+ tree: {
80
+ "Inhibitie" => {
81
+ "male" => {
82
+ (10.0...11.0) => {
83
+ (-Float::INFINITY...10.5) => 39.0,
84
+ (10.5...20.1) => 42.0,
85
+ (20.1...30.7) => 71.0,
86
+ (30.7...Float::INFINITY) => 75.0
87
+ }
88
+ }
89
+ }
90
+ }
91
+ )
92
+ end
72
93
 
73
94
  it 'returns the correct scores' do
74
95
  params = {age: 10, raw: 15.8, scale: 'Inhibitie', gender: 'male'}
@@ -80,7 +101,12 @@ describe Quby::TableBackend::RangeTree do
80
101
  end
81
102
 
82
103
  describe 'definition containing float values' do
83
- let(:csv_key) { 'test2' }
104
+ let(:tree) do
105
+ described_class.new(
106
+ levels: ["scale", "raw", "norm"],
107
+ tree: {"Inhibitie" => {15.0=>39.0, 16.0=>42.0, 17.0=>71.0, 18.0=>75.0}}
108
+ )
109
+ end
84
110
 
85
111
  it 'returns the correct scores when using integers in lookup path' do
86
112
  params = {scale: 'Inhibitie', raw: 17}
@@ -94,6 +94,5 @@ RSpec.configure do |config|
94
94
  config.before(:each) do
95
95
  Quby.questionnaire_repo = Quby::Questionnaires::Repos::DiskRepo.new(Quby.fixtures_path)
96
96
  Quby.answer_repo = Quby::Answers::Repos::MemoryRepo.new
97
- Quby.lookup_table_repo = Quby::LookupTableRepo::Disk.new(Rails.root.join('..', 'fixtures', 'lookup_tables'))
98
97
  end
99
98
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quby
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0.pre2
4
+ version: 5.0.0.pre3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marten Veldthuis
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2020-10-27 00:00:00.000000000 Z
14
+ date: 2020-10-29 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rails
@@ -750,8 +750,6 @@ files:
750
750
  - lib/quby/answers/specs/api_specs.rb
751
751
  - lib/quby/answers/specs/repo_specs.rb
752
752
  - lib/quby/engine.rb
753
- - lib/quby/lookup_table.rb
754
- - lib/quby/lookup_table_repo.rb
755
753
  - lib/quby/markdown_parser.rb
756
754
  - lib/quby/pdf_renderer.rb
757
755
  - lib/quby/questionnaires.rb
@@ -810,7 +808,6 @@ files:
810
808
  - spec/active_model_modules/type_validator_spec.rb
811
809
  - spec/benchmarks/answer_instantiation_speed_spec.rb
812
810
  - spec/benchmarks/large_questionnaire_spec.rb
813
- - spec/benchmarks/load_normscore_csv.rb
814
811
  - spec/controllers/quby/answers_controller/authorize_with_hmac_spec.rb
815
812
  - spec/controllers/quby/answers_controller/authorize_with_id_from_session_spec.rb
816
813
  - spec/controllers/quby/answers_controller_spec.rb
@@ -6380,8 +6377,6 @@ files:
6380
6377
  - spec/quby/answers/services/text_transformation_spec.rb
6381
6378
  - spec/quby/answers/services/updates_answers_spec.rb
6382
6379
  - spec/quby/i18n_spec.rb
6383
- - spec/quby/lookup_table_repo_spec.rb
6384
- - spec/quby/lookup_table_spec.rb
6385
6380
  - spec/quby/markdown_parser_spec.rb
6386
6381
  - spec/quby/pdf_renderer_spec.rb
6387
6382
  - spec/quby/questionnaires/deserializer/questionnaire_spec.rb
@@ -6521,10 +6516,8 @@ test_files:
6521
6516
  - spec/quby/answers/entities/score_spec.rb
6522
6517
  - spec/quby/answers/entities/patient_spec.rb
6523
6518
  - spec/quby/answers/entities/answer_spec.rb
6524
- - spec/quby/lookup_table_spec.rb
6525
6519
  - spec/quby/pdf_renderer_spec.rb
6526
6520
  - spec/quby/markdown_parser_spec.rb
6527
- - spec/quby/lookup_table_repo_spec.rb
6528
6521
  - spec/spec.opts
6529
6522
  - spec/features/hiding_questions_spec.rb
6530
6523
  - spec/features/javascript_question_dependencies_spec.rb
@@ -12060,7 +12053,6 @@ test_files:
12060
12053
  - spec/support/validation_helpers.rb
12061
12054
  - spec/support/feature_helpers.rb
12062
12055
  - spec/benchmarks/large_questionnaire_spec.rb
12063
- - spec/benchmarks/load_normscore_csv.rb
12064
12056
  - spec/benchmarks/answer_instantiation_speed_spec.rb
12065
12057
  - spec/javascripts/ajax_callbacks_spec.coffee
12066
12058
  - spec/javascripts/init_questions_spec.coffee
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'quby/table_backend/range_tree'
4
-
5
- module Quby
6
- class LookupTable
7
- attr_accessor :key
8
-
9
- def initialize(key)
10
- @key = key
11
- end
12
-
13
- def backing
14
- return @backing if @backing.present?
15
- all_data = data
16
- headers = all_data.shift
17
- compare = all_data.shift
18
- @backing = Quby::TableBackend::RangeTree.from_csv(levels: headers, compare: compare, data: all_data)
19
- end
20
-
21
- def lookup(parameters)
22
- backing.lookup(parameters)
23
- end
24
-
25
- def data
26
- Quby.lookup_table_repo.retrieve(key)
27
- end
28
- end
29
- end
@@ -1,24 +0,0 @@
1
- require 'pathname'
2
- require 'csv'
3
-
4
- module Quby
5
- module LookupTableRepo
6
- def self.validate_key(key)
7
- raise 'invalid key' unless key =~ /\A[a-z][a-z_0-9]{1,50}\z/
8
- end
9
-
10
- class Disk
11
- attr_reader :disk_table_root
12
-
13
- def initialize(disk_table_root)
14
- @disk_table_root = Pathname.new(disk_table_root)
15
- end
16
-
17
- def retrieve(key)
18
- Quby::LookupTableRepo.validate_key(key)
19
- path = disk_table_root.join(key + '.csv')
20
- CSV.read(path, col_sep: ';', skip_blanks: true)
21
- end
22
- end
23
- end
24
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- feature 'Load normscore csv file', benchmark: true do
6
- it 'loads a csv file' do
7
- 10.times do
8
- Quby.lookup_table_repo.retrieve('test')
9
- end
10
- end
11
-
12
- it 'builds a tree' do
13
- data = Quby.lookup_table_repo.retrieve('test')
14
- 10.times do
15
- Quby::TableBackend::RangeTree.new(data).send :tree
16
- end
17
- end
18
- end
@@ -1,20 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Quby::LookupTableRepo::Disk do
4
- subject { Quby.lookup_table_repo }
5
-
6
- it 'Quby.lookup_table_repo is a disk repo by default' do
7
- expect(subject).to be_an_instance_of(described_class)
8
- end
9
-
10
- describe '#retrieve' do
11
- it 'reads the csv file' do
12
- expect(CSV).to receive(:read).and_call_original
13
- subject.retrieve 'test'
14
- end
15
-
16
- it 'fails when csv file is not found' do
17
- expect { subject.retrieve 'not_there' }.to raise_error(Errno::ENOENT)
18
- end
19
- end
20
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- module Quby
6
- describe LookupTable do
7
- let(:table) { described_class.new('test') }
8
- let(:fake_backing) { double(:"present?" => true).as_null_object }
9
-
10
- describe '#lookup' do
11
- it 'passes lookup calls on to the backing' do
12
- expect(Quby::TableBackend::RangeTree).to receive(:from_csv).and_return(fake_backing)
13
- parameters = {a: 1}
14
- expect(table.backing).to receive(:lookup).with(parameters)
15
- table.lookup(parameters)
16
- end
17
-
18
- it 'initializes the disktree lazily' do
19
- headers = double
20
- compare = double
21
- data = double
22
- data_double = [headers, compare, data]
23
- table
24
- expect_any_instance_of(described_class).to receive(:data).and_return(data_double)
25
- expect(Quby::TableBackend::RangeTree).to receive(:from_csv).with(levels: headers, compare: compare, data:[data]).and_return(fake_backing)
26
- table.lookup(some: :thing)
27
- end
28
- end
29
-
30
- describe '#data' do
31
- it 'calls Quby.lookup_table_repo.retrieve(table.key)' do
32
- table
33
- expect(Quby.lookup_table_repo).to receive(:retrieve).with(table.key)
34
- table.data
35
- end
36
- end
37
- end
38
- end