ncs_mdes_warehouse 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/CHANGELOG.md +16 -0
  2. data/generated_models/ncs_navigator/warehouse/models/two_point_zero/env_equipment_prob_log.rb +1 -1
  3. data/generated_models/ncs_navigator/warehouse/models/two_point_zero/incident.rb +6 -6
  4. data/generated_models/ncs_navigator/warehouse/models/two_point_zero/participant_rvis.rb +1 -1
  5. data/generated_models/ncs_navigator/warehouse/models/two_point_zero/sample_shipping.rb +1 -1
  6. data/lib/ncs_navigator/warehouse.rb +4 -0
  7. data/lib/ncs_navigator/warehouse/cli.rb +31 -1
  8. data/lib/ncs_navigator/warehouse/configuration.rb +49 -9
  9. data/lib/ncs_navigator/warehouse/database_initializer.rb +62 -4
  10. data/lib/ncs_navigator/warehouse/models.rb +3 -0
  11. data/lib/ncs_navigator/warehouse/postgresql.rb +7 -0
  12. data/lib/ncs_navigator/warehouse/postgresql/pgpass.rb +79 -0
  13. data/lib/ncs_navigator/warehouse/table_modeler/mdes_ext.rb +9 -0
  14. data/lib/ncs_navigator/warehouse/table_modeler/model_template.rb.erb +1 -1
  15. data/lib/ncs_navigator/warehouse/transform_load.rb +55 -0
  16. data/lib/ncs_navigator/warehouse/transform_status.rb +63 -0
  17. data/lib/ncs_navigator/warehouse/transformers.rb +0 -1
  18. data/lib/ncs_navigator/warehouse/transformers/database.rb +91 -85
  19. data/lib/ncs_navigator/warehouse/transformers/enum_transformer.rb +26 -8
  20. data/lib/ncs_navigator/warehouse/transformers/vdr_xml.rb +1 -1
  21. data/lib/ncs_navigator/warehouse/transformers/vdr_xml/reader.rb +11 -4
  22. data/lib/ncs_navigator/warehouse/version.rb +1 -1
  23. data/spec/bcdatabase/test_sqlite.yml +4 -0
  24. data/spec/ncs_navigator/warehouse/configuration_spec.rb +42 -0
  25. data/spec/ncs_navigator/warehouse/postgresql/pgpass_spec.rb +187 -0
  26. data/spec/ncs_navigator/warehouse/table_modeler_spec.rb +15 -1
  27. data/spec/ncs_navigator/warehouse/transform_load_spec.rb +152 -0
  28. data/spec/ncs_navigator/warehouse/transformers/database_spec.rb +24 -28
  29. data/spec/ncs_navigator/warehouse/transformers/enum_transformer_spec.rb +16 -10
  30. data/spec/ncs_navigator/warehouse/transformers/vdr_xml/made_up_vdr_xml.xml +4 -4
  31. data/spec/ncs_navigator/warehouse/transformers/vdr_xml/reader_spec.rb +8 -3
  32. data/spec/spec_helper.rb +1 -1
  33. metadata +44 -37
  34. data/lib/ncs_navigator/warehouse/transformers/transform_status.rb +0 -23
@@ -9,7 +9,7 @@ module NcsNavigator::Warehouse::Transformers
9
9
  # @return [#transform] a transformer that loads the MDES data in
10
10
  # the specified VDR XML file.
11
11
  def from_file(config, filename) # <- TODO better solution
12
- EnumTransformer.new(Reader.new(config, filename))
12
+ EnumTransformer.new(config, Reader.new(config, filename))
13
13
  end
14
14
 
15
15
  ##
@@ -46,8 +46,9 @@ class NcsNavigator::Warehouse::Transformers::VdrXml
46
46
  @start = Time.now
47
47
 
48
48
  Nokogiri::XML::Reader(@io).each do |node|
49
- # 1 is an open element, 15 is a close
50
- next unless [1, 15].include?(node.node_type)
49
+ element_types = [:TYPE_ELEMENT, :TYPE_END_ELEMENT].
50
+ collect { |c| Nokogiri::XML::Reader.const_get(c) }
51
+ next unless element_types.include?(node.node_type)
51
52
  encounter_node(node, node.node_type == 1, &block)
52
53
  end
53
54
 
@@ -77,8 +78,14 @@ class NcsNavigator::Warehouse::Transformers::VdrXml
77
78
  # node is the start tag of a table variable
78
79
  var = node.local_name.to_sym
79
80
  val = node.inner_xml.strip
80
- node.read # skip contents (read as 'var' above)
81
- node.read # skip close tag
81
+
82
+ unless node.self_closing?
83
+ # Skip to closing tag
84
+ n = node.read
85
+ until n.node_type == Nokogiri::XML::Reader::TYPE_END_ELEMENT
86
+ n = node.read
87
+ end
88
+ end
82
89
 
83
90
  unless should_filter_out(@current_model_class, var, val)
84
91
  @current_parameter_values[var] = val
@@ -1,5 +1,5 @@
1
1
  module NcsNavigator
2
2
  module Warehouse
3
- VERSION = '0.0.2'
3
+ VERSION = '0.1.0'
4
4
  end
5
5
  end
@@ -3,3 +3,7 @@ defaults:
3
3
  datamapper_adapter: sqlite
4
4
  people_pro:
5
5
  database: people_pro.sqlite3
6
+ mdes_warehouse_reporting:
7
+ database: wh_reporting.sqlite3
8
+ mdes_warehouse_working:
9
+ database: wh_working.sqlite3
@@ -328,6 +328,48 @@ module NcsNavigator::Warehouse
328
328
  end
329
329
  end
330
330
 
331
+ describe '#pg_bin_path' do
332
+ it 'defaults to nil' do
333
+ config.pg_bin_path.should be_nil
334
+ end
335
+
336
+ describe 'when set' do
337
+ before do
338
+ config.pg_bin_path = '/Library/PostgreSQL/9.0/bin'
339
+ end
340
+
341
+ it 'is retrievable' do
342
+ config.pg_bin_path.to_s.should == '/Library/PostgreSQL/9.0/bin'
343
+ end
344
+
345
+ it 'becomes a Pathname' do
346
+ config.pg_bin_path.should be_a Pathname
347
+ end
348
+ end
349
+ end
350
+
351
+ describe '#pg_bin' do
352
+ describe 'with no path' do
353
+ before do
354
+ config.pg_bin_path = nil
355
+ end
356
+
357
+ it 'prepends nothing' do
358
+ config.pg_bin('pg_dumpall').to_s.should == 'pg_dumpall'
359
+ end
360
+ end
361
+
362
+ describe 'with a path' do
363
+ before do
364
+ config.pg_bin_path = '/home/me/bin'
365
+ end
366
+
367
+ it 'prepends the path' do
368
+ config.pg_bin('pg_dumpall').to_s.should == '/home/me/bin/pg_dumpall'
369
+ end
370
+ end
371
+ end
372
+
331
373
  describe '.from_file' do
332
374
  let(:filename) { tmpdir + 'test.rb' }
333
375
  subject { Configuration.from_file(filename) }
@@ -0,0 +1,187 @@
1
+ require File.expand_path('../../../../spec_helper', __FILE__)
2
+
3
+ module NcsNavigator::Warehouse::PostgreSQL
4
+ describe Pgpass do
5
+ let(:home) { tmpdir('home') }
6
+ let(:file) { home + '.pgpass' }
7
+
8
+ before do
9
+ @original_home, ENV['HOME'] = ENV['HOME'], home
10
+ end
11
+
12
+ after do
13
+ ENV['HOME'] = @original_home
14
+ end
15
+
16
+ describe '#file' do
17
+ it 'defaults to $HOME/.pgpass' do
18
+ Pgpass.new.file.should == file
19
+ end
20
+ end
21
+
22
+ describe '.line' do
23
+ subject { Pgpass.line entry }
24
+ let(:entry) {
25
+ {
26
+ 'username' => 'warehouse',
27
+ 'password' => 'volt',
28
+ 'database' => 'ignored'
29
+ }
30
+ }
31
+
32
+ it 'includes defaults for host and port if not set' do
33
+ subject.should == %w(localhost 5432 * warehouse volt)
34
+ end
35
+
36
+ it 'uses an explicit host if available' do
37
+ entry['host'] = 'ncs_db'
38
+ subject.should == %w(ncs_db 5432 * warehouse volt)
39
+ end
40
+
41
+ it 'uses an explicit port if available' do
42
+ entry['port'] = 5439
43
+ subject.should == %w(localhost 5439 * warehouse volt)
44
+ end
45
+
46
+ it 'fails without a username' do
47
+ entry.delete 'username'
48
+ lambda { subject }.should raise_error(/No username in configuration/)
49
+ end
50
+
51
+ it 'fails without a password' do
52
+ entry.delete 'password'
53
+ lambda { subject }.should raise_error(/No password in configuration/)
54
+ end
55
+ end
56
+
57
+ describe '#update' do
58
+ subject { Pgpass.new }
59
+ let(:entry) {
60
+ {
61
+ 'username' => 'mw',
62
+ 'password' => 'fishes',
63
+ 'host' => 'ncsdb',
64
+ 'port' => 5500,
65
+ 'database' => 'mw_r'
66
+ }
67
+ }
68
+ let(:lines) {
69
+ file.readlines.collect { |l| l.chomp.split ':' }
70
+ }
71
+ let(:expected_line) { "ncsdb:5500:*:mw:fishes\n" }
72
+
73
+ describe 'when the file exists' do
74
+ describe 'and the same line exists' do
75
+ before do
76
+ file.open('w') do |f|
77
+ f.puts 'somewhere:5400:*:aguy:five'
78
+ f.puts 'ncsdb:5500:*:mw:fishes'
79
+ f.puts 'somewhere:5400:*:someoneelse:yet'
80
+ end
81
+
82
+ subject.update(entry)
83
+ end
84
+
85
+ it 'does nothing' do
86
+ lines.collect { |l| l[3] }.should == %w(aguy mw someoneelse)
87
+ end
88
+ end
89
+
90
+ describe 'and a similar line with a different password exists' do
91
+ before do
92
+ file.open('w') do |f|
93
+ f.puts 'somewhere:5400:*:aguy:five'
94
+ f.puts 'ncsdb:5500:*:mw:shark'
95
+ f.puts 'ncsdb:5500:*:someoneelse:fred'
96
+ f.puts 'somewhere:5400:*:someoneelse:yet'
97
+ end
98
+
99
+ subject.update(entry)
100
+ end
101
+
102
+ it 'updates the password' do
103
+ file.readlines[1].should == expected_line
104
+ end
105
+
106
+ it 'leaves other entries alone' do
107
+ lines.collect { |l| l[4] }.should == %w(five fishes fred yet)
108
+ end
109
+ end
110
+
111
+ describe 'and no similar entry exists' do
112
+ before do
113
+ file.open('w') do |f|
114
+ f.puts 'somewhere:5400:*:aguy:five'
115
+ f.puts 'ncsdb:5500:*:someoneelse:fred'
116
+ f.puts 'somewhere:5400:*:someoneelse:yet'
117
+ end
118
+
119
+ subject.update(entry)
120
+ end
121
+
122
+ it 'adds the entry' do
123
+ file.readlines.last.should == expected_line
124
+ end
125
+
126
+ it 'leaves the other entries alone' do
127
+ lines.collect { |l| l[0] }.should == %w(somewhere ncsdb somewhere ncsdb)
128
+ end
129
+ end
130
+ end
131
+
132
+ describe 'when the file does not exist' do
133
+ before do
134
+ file.exist?.should be_false
135
+
136
+ subject.update(entry)
137
+ end
138
+
139
+ it 'creates the file' do
140
+ file.exist?.should be_true
141
+ end
142
+
143
+ it 'sets the permissions to user-rw only' do
144
+ `ls -al '#{file}'`.should =~ /^-rw------/
145
+ end
146
+
147
+ it 'adds the appropriate entry' do
148
+ file.readlines.should == [expected_line]
149
+ end
150
+ end
151
+
152
+ describe 'when the directory does not exist' do
153
+ before do
154
+ home.rmdir
155
+ end
156
+
157
+ it 'fails' do
158
+ lambda { subject.update(entry) }.should(
159
+ raise_error %r{Cannot create #{home}/.pgpass})
160
+ end
161
+ end
162
+
163
+ describe 'when the directory is not writable' do
164
+ before do
165
+ home.chmod(0500)
166
+ end
167
+
168
+ it 'fails' do
169
+ lambda { subject.update(entry) }.should(
170
+ raise_error %r{Cannot create #{home}/.pgpass})
171
+ end
172
+ end
173
+
174
+ describe 'when the file exists but is not writable' do
175
+ before do
176
+ file.open('w') { |f| }
177
+ file.chmod(0500)
178
+ end
179
+
180
+ it 'fails' do
181
+ lambda { subject.update(entry) }.should(
182
+ raise_error %r{Cannot update #{home}/.pgpass})
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
@@ -449,8 +449,10 @@ end
449
449
  end
450
450
  end
451
451
 
452
+ let(:child_variable_name) { 'some_tree_id' }
453
+
452
454
  before do
453
- table.variables << NcsNavigator::Mdes::Variable.new('some_tree_id').tap do |v|
455
+ table.variables << NcsNavigator::Mdes::Variable.new(child_variable_name).tap do |v|
454
456
  v.table_reference = parent_table
455
457
  v.type = NcsNavigator::Mdes::VariableType.new('foreignKeyRequiredType').tap do |vt|
456
458
  vt.base_type = :string
@@ -502,6 +504,18 @@ end
502
504
 
503
505
  instance.should_not be_valid
504
506
  end
507
+
508
+ describe 'when the child key does not have the "_id" suffix' do
509
+ let(:child_variable_name) { 'some_tree' }
510
+
511
+ it 'has an object reference accessor' do
512
+ model_class.instance_methods.collect(&:to_s).should include('some_tree_record')
513
+ end
514
+
515
+ it 'does not have a suffixed ID attribute' do
516
+ model_class.instance_methods.collect(&:to_s).should_not include('some_tree_id')
517
+ end
518
+ end
505
519
  end
506
520
  end
507
521
 
@@ -0,0 +1,152 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ module NcsNavigator::Warehouse
4
+ describe TransformLoad, :modifies_warehouse_state do
5
+ let(:config) { base_config }
6
+ let(:loader) { TransformLoad.new(config) }
7
+
8
+ def base_config
9
+ Configuration.new.tap do |c|
10
+ c.bcdatabase_group = :test_sqlite
11
+ c.log_file = tmpdir + "#{File.basename(__FILE__)}.log"
12
+ c.output_level = :quiet
13
+ end
14
+ end
15
+
16
+ before(:all) do
17
+ # Not config due to RSpec #500
18
+ DatabaseInitializer.new(base_config).tap do |dbi|
19
+ dbi.set_up_repository(:both)
20
+ end
21
+ TransformError.auto_migrate!(:mdes_warehouse_working)
22
+ TransformStatus.auto_migrate!(:mdes_warehouse_working)
23
+ end
24
+
25
+ describe '#run' do
26
+ it 'runs the transformers in the order specified' do
27
+ order = []
28
+ config.add_transformer(BlockTransformer.new { |s| order << 'B' })
29
+ config.add_transformer(BlockTransformer.new { |s| order << 'T' })
30
+ config.add_transformer(BlockTransformer.new { |s| order << 'w' })
31
+
32
+ loader.run
33
+
34
+ order.should == %w(B T w)
35
+ end
36
+
37
+ it 'passes a separate instance of TransformStatus to each transformer' do
38
+ statuses = []
39
+ config.add_transformer(BlockTransformer.new { |s| statuses << s })
40
+ config.add_transformer(BlockTransformer.new { |s| statuses << s })
41
+
42
+ loader.run
43
+
44
+ statuses.first.should_not be statuses.last
45
+ end
46
+
47
+ describe 'a created status' do
48
+ let(:statuses) { [] }
49
+ let(:status) { statuses.first }
50
+ let(:transformer) { BlockTransformer.new { |s| statuses << s } }
51
+
52
+ before do
53
+ config.add_transformer(transformer)
54
+ end
55
+
56
+ it 'uses the name provided by the transformer, if any' do
57
+ def transformer.name; 'provided'; end
58
+
59
+ loader.run
60
+
61
+ status.name.should == 'provided'
62
+ end
63
+
64
+ it 'uses the class name of the transformer otherwise' do
65
+ loader.run
66
+
67
+ status.name.should == 'BlockTransformer'
68
+ end
69
+
70
+ it 'sets the start and end times' do
71
+ Time.should_receive(:now).and_return(Time.iso8601('2001-01-12T08:00:00'))
72
+ Time.stub!(:now).and_return(Time.iso8601('2001-01-12T09:06:30'))
73
+
74
+ loader.run
75
+
76
+ status.start_time.hour.should == 8
77
+ status.end_time.hour.should == 9
78
+ end
79
+
80
+ it 'sets the position' do
81
+ loader.run
82
+ status.position.should == 0
83
+ end
84
+ end
85
+
86
+ it 'returns true if none of the transformers report an error' do
87
+ config.add_transformer(BlockTransformer.new { |s| })
88
+ loader.run.should be_true
89
+ end
90
+
91
+ describe 'with a reported error' do
92
+ let(:runs) { [] }
93
+
94
+ before do
95
+ config.add_transformer(BlockTransformer.new { |s| runs << 'A' })
96
+ config.add_transformer(BlockTransformer.new { |s|
97
+ runs << 'B'
98
+ s.unsuccessful_record(nil, 'fail')
99
+ })
100
+ config.add_transformer(BlockTransformer.new { |s| runs << 'C3' })
101
+ @result = loader.run
102
+ end
103
+
104
+ it 'still runs all the transformers' do
105
+ runs.should == %w(A B C3)
106
+ end
107
+
108
+ it 'returns false' do
109
+ @result.should == false
110
+ end
111
+ end
112
+
113
+ describe 'with a failure' do
114
+ let(:runs) { [] }
115
+
116
+ before do
117
+ config.add_transformer(BlockTransformer.new { |s| runs << 'A' })
118
+ config.add_transformer(BlockTransformer.new { |s|
119
+ runs << 'B'
120
+ fail 'No thanks.'
121
+ })
122
+ config.add_transformer(BlockTransformer.new { |s| runs << 'C3' })
123
+ @result = loader.run
124
+ end
125
+
126
+ it 'still runs all the transformers' do
127
+ runs.should == %w(A B C3)
128
+ end
129
+
130
+ it 'returns false' do
131
+ @result.should == false
132
+ end
133
+ end
134
+
135
+ describe 'sending e-mail' do
136
+ it 'sends on success'
137
+
138
+ it 'sends on failure'
139
+ end
140
+ end
141
+
142
+ class ::BlockTransformer
143
+ def initialize(&block)
144
+ @block = block
145
+ end
146
+
147
+ def transform(status)
148
+ @block.call(status)
149
+ end
150
+ end
151
+ end
152
+ end