ndr_import 11.1.0 → 11.2.1

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: 1acf9db0301b6da991e890e74db10573ff666dd732eda4b58ba90e03370bb32a
4
- data.tar.gz: eba9da2d2d9f5fa98c3a7f8745086f3945c363844f4d1f8fc1dc6c38ab4bcb5b
3
+ metadata.gz: 77f2f2adb4de01a7dca5f2e004976a0f96e8d486f4bf573e24543c1a27b894dd
4
+ data.tar.gz: eb83c8b95408ee9761b513c9e9309a6b565fd937e7cfba585088bd3d7e7b2573
5
5
  SHA512:
6
- metadata.gz: 8509511d4f54f36344e09d380da53f168f8fa94efd4eec2d73e29c80811bd644d853bb82a835bf7ddf2820202b8abad28cbe0d265de3557e2af8adca4f12b178
7
- data.tar.gz: 384d8365d4e6ba741bf6b76a1ecfe1bf1bb92c6fd0e737489d2d3a13047d9e557b883c339ff2f89f372071140a071bcbedfdd303b588dda79d58870bab0be2e6
6
+ metadata.gz: 6dcfa45678b041cbe5c298b43c935aa2dacc47da9421cfbc6d6f8e646049f89326fb7a7a41e6e5ea283a1114ce367e7cff92d77dd4b83db56775e1d69a93fc6e
7
+ data.tar.gz: 2443a1c7b4ab1f1c8fcc105cf7c3d29b1885f996e41ad55b65f0ea74d64fbe43042d50a2bb3943a5563374aa8bdc0dd3d47e066226f010922f1fd7e69c167641
data/CHANGELOG.md CHANGED
@@ -1,7 +1,14 @@
1
1
  ## [Unreleased]
2
- =======
3
2
  * no unreleased changes *
4
3
 
4
+ ## 11.2.1 / 2024-11-18
5
+ ### Fixed
6
+ * Support Ruby 3.2 and 3.3, Rails 7.1, 7.2 and 8.0
7
+
8
+ ## 11.2.0 / 2024-04-10
9
+ ### Added
10
+ * XML file/table metadata storage
11
+
5
12
  ## 11.1.0 / 2024-03-07
6
13
  ### Added
7
14
  * XML table should not expect column mappings for empty nodes/elements
@@ -49,8 +49,12 @@ class << CSVLibrary
49
49
 
50
50
  private
51
51
 
52
+ def deprecator
53
+ @deprecator ||= ActiveSupport::Deprecation.new(NdrImport::VERSION, 'NdrImport')
54
+ end
55
+
52
56
  def deprecate(additional_message = nil)
53
- ActiveSupport::Deprecation.warn(<<~MESSAGE)
57
+ deprecator.warn(<<~MESSAGE)
54
58
  CSVLibrary is deprecated, and will be removed in a future version of ndr_import.
55
59
  Please use standard functionality provided by Ruby's CSV library (#{additional_message}).
56
60
  MESSAGE
@@ -9,6 +9,8 @@ module NdrImport
9
9
  module File
10
10
  # All common base file handler logic is defined here.
11
11
  class Base
12
+ attr_accessor :file_metadata
13
+
12
14
  def initialize(filename, format, options = {})
13
15
  @filename = filename
14
16
  @format = format
@@ -32,10 +34,10 @@ module NdrImport
32
34
  yield @filename
33
35
  end
34
36
 
35
- # This method iterates over the tables in the given file and yields with two arguments:
36
- # a tablename and a row enumerator (for that table). For a spreadsheet it may yield for
37
- # every worksheet in the file and for a CSV file it will only yield once (the entire
38
- # file is one table).
37
+ # This method iterates over the tables in the given file and yields with three arguments:
38
+ # a tablename, a row enumerator (for that table) and any file metadata.
39
+ # For a spreadsheet it may yield for every worksheet in the file and for a CSV file it
40
+ # will only yield once (the entire file is one table).
39
41
  #
40
42
  # As single table files are in the majority, the Base implementation is defined for
41
43
  # single table handlers and you will only need to implement the rows iterator. If your
@@ -45,7 +47,7 @@ module NdrImport
45
47
  def tables
46
48
  return enum_for(:tables) unless block_given?
47
49
 
48
- yield nil, rows
50
+ yield nil, rows, file_metadata
49
51
  end
50
52
 
51
53
  private
@@ -16,18 +16,73 @@ module NdrImport
16
16
  super
17
17
 
18
18
  @pattern_match_xpath = @options['pattern_match_record_xpath']
19
+ @xml_file_metadata = @options['xml_file_metadata']
20
+ @options['slurp'] ? prepare_slurped_file : prepare_streamed_file
19
21
  end
20
22
 
21
23
  private
22
24
 
25
+ def prepare_slurped_file
26
+ @doc = read_xml_file(@filename)
27
+ slurp_metadata_values
28
+ end
29
+
30
+ def prepare_streamed_file
31
+ with_encoding_check(@filename) do |stream, encoding|
32
+ @stream = stream
33
+ @encoding = encoding
34
+ end
35
+ stream_metadata_values
36
+ end
37
+
38
+ def slurp_metadata_values
39
+ return unless @xml_file_metadata.is_a?(Hash)
40
+
41
+ self.file_metadata = @xml_file_metadata.transform_values do |xpath|
42
+ @doc.xpath(xpath).inner_text
43
+ end
44
+ end
45
+
46
+ def stream_metadata_values
47
+ return unless @xml_file_metadata.is_a?(Hash)
48
+
49
+ self.file_metadata = @xml_file_metadata.transform_values.with_index do |xpath, index|
50
+ # Ensure we're at the start of the stream each time
51
+ @stream.rewind unless index.zero?
52
+
53
+ metadata_from_stream(xpath)
54
+ end
55
+ end
56
+
57
+ def metadata_from_stream(xpath)
58
+ cursor = Cursor.new(xpath, false)
59
+
60
+ # If markup isn't well-formed, try to work around it:
61
+ options = Nokogiri::XML::ParseOptions::RECOVER
62
+ reader = Nokogiri::XML::Reader(@stream, nil, @encoding, options)
63
+
64
+ reader.each do |node|
65
+ case node.node_type
66
+ when Nokogiri::XML::Reader::TYPE_ELEMENT # "opening tag"
67
+ raise NestingError, node if cursor.in?(node)
68
+
69
+ cursor.enter(node)
70
+ return cursor.inner_text if cursor.send(:current_stack_match?)
71
+ when Nokogiri::XML::Reader::TYPE_END_ELEMENT # "closing tag"
72
+ cursor.leave(node)
73
+ end
74
+ end
75
+ end
76
+
23
77
  # Iterate through the file, yielding each 'xml_record_xpath' element in turn.
24
78
  def rows(&block)
25
79
  return enum_for(:rows) unless block
26
80
 
27
81
  if @options['slurp']
28
- record_elements(read_xml_file(@filename)).each(&block)
82
+ record_elements.each(&block)
29
83
  else
30
- each_node(@filename, xml_record_xpath, @pattern_match_xpath, &block)
84
+ @stream.rewind
85
+ each_node(@stream, @encoding, xml_record_xpath, @pattern_match_xpath, &block)
31
86
  end
32
87
  end
33
88
 
@@ -35,13 +90,13 @@ module NdrImport
35
90
  @pattern_match_xpath ? @options['xml_record_xpath'] : "*/#{@options['xml_record_xpath']}"
36
91
  end
37
92
 
38
- def record_elements(doc)
93
+ def record_elements
39
94
  if @pattern_match_xpath
40
- doc.root.children.find_all do |element|
95
+ @doc.root.children.find_all do |element|
41
96
  element.name =~ Regexp.new(@options['xml_record_xpath'])
42
97
  end
43
98
  else
44
- doc.root.xpath(@options['xml_record_xpath'])
99
+ @doc.root.xpath(@options['xml_record_xpath'])
45
100
  end
46
101
  end
47
102
  end
@@ -78,6 +78,10 @@ module NdrImport
78
78
  match
79
79
  end
80
80
 
81
+ def inner_text
82
+ dom_stubs[@stack].xpath(@xpath)&.inner_text
83
+ end
84
+
81
85
  private
82
86
 
83
87
  def in_empty_element?
@@ -134,21 +138,18 @@ module NdrImport
134
138
 
135
139
  include UTF8Encoding
136
140
 
137
- # Streams the contents of the given `safe_path`, and yields
138
- # each element matching `xpath` as they're found.
141
+ # Yields each element matching `xpath` from `stream` as they're found.
139
142
  #
140
143
  # In the case of dodgy encoding, may fall back to slurping the
141
144
  # file, but will still use stream parsing for XML.
142
145
  #
143
146
  # Optionally pattern match the xpath
144
- def each_node(safe_path, xpath, pattern_match_xpath = nil, &block)
145
- return enum_for(:each_node, safe_path, xpath, pattern_match_xpath) unless block
147
+ def each_node(stream, encoding, xpath, pattern_match_xpath = nil, &block)
148
+ return enum_for(:each_node, stream, encoding, xpath, pattern_match_xpath) unless block
146
149
 
147
150
  require 'nokogiri'
148
151
 
149
- with_encoding_check(safe_path) do |stream, encoding|
150
- stream_xml_nodes(stream, xpath, pattern_match_xpath, encoding, &block)
151
- end
152
+ stream_xml_nodes(stream, xpath, pattern_match_xpath, encoding, &block)
152
153
  end
153
154
 
154
155
  private
@@ -21,7 +21,7 @@ module NdrImport
21
21
  end
22
22
 
23
23
  attr_reader(*all_valid_options)
24
- attr_accessor :notifier
24
+ attr_accessor :notifier, :table_metadata
25
25
 
26
26
  def initialize(options = {})
27
27
  options.stringify_keys! if options.is_a?(Hash)
@@ -59,7 +59,8 @@ module NdrImport
59
59
  'xml_record_xpath' => table_mapping.try(:xml_record_xpath),
60
60
  'slurp' => table_mapping.try(:slurp),
61
61
  'yield_xml_record' => table_mapping.try(:yield_xml_record),
62
- 'pattern_match_record_xpath' => table_mapping.try(:pattern_match_record_xpath) }
62
+ 'pattern_match_record_xpath' => table_mapping.try(:pattern_match_record_xpath),
63
+ 'xml_file_metadata' => table_mapping.try(:xml_file_metadata) }
63
64
 
64
65
  tables = NdrImport::File::Registry.tables(filename, table_mapping.try(:format), options)
65
66
  yield_tables_and_their_content(filename, tables, &block)
@@ -71,12 +72,12 @@ module NdrImport
71
72
  def yield_tables_and_their_content(filename, tables, &block)
72
73
  return enum_for(:yield_tables_and_their_content, filename, tables) unless block_given?
73
74
 
74
- tables.each do |tablename, table_content|
75
+ tables.each do |tablename, table_content, file_metadata|
75
76
  mapping = get_table_mapping(filename, tablename)
76
77
  next if mapping.nil?
77
78
 
78
79
  mapping.notifier = get_notifier(record_total(filename, table_content))
79
-
80
+ mapping.table_metadata = file_metadata || {}
80
81
  yield(mapping, table_content)
81
82
  end
82
83
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  # This stores the current version of the NdrImport gem
3
3
  module NdrImport
4
- VERSION = '11.1.0'
4
+ VERSION = '11.2.1'
5
5
  end
@@ -10,7 +10,8 @@ module NdrImport
10
10
  require 'ndr_import/xml/column_mapping'
11
11
  require 'ndr_import/xml/masked_mappings'
12
12
 
13
- XML_OPTIONS = %w[pattern_match_record_xpath xml_record_xpath yield_xml_record].freeze
13
+ XML_OPTIONS = %w[pattern_match_record_xpath xml_file_metadata xml_record_xpath
14
+ yield_xml_record].freeze
14
15
 
15
16
  def self.all_valid_options
16
17
  super - %w[delimiter header_lines footer_lines] + XML_OPTIONS
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ndr_import
3
3
  version: !ruby/object:Gem::Version
4
- version: 11.1.0
4
+ version: 11.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - NCRS Development Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-03-07 00:00:00.000000000 Z
11
+ date: 2024-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: '6.1'
34
34
  - - "<"
35
35
  - !ruby/object:Gem::Version
36
- version: '7.1'
36
+ version: '8.1'
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '6.1'
44
44
  - - "<"
45
45
  - !ruby/object:Gem::Version
46
- version: '7.1'
46
+ version: '8.1'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: ndr_support
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -120,6 +120,20 @@ dependencies:
120
120
  - - "~>"
121
121
  - !ruby/object:Gem::Version
122
122
  version: 0.9.5
123
+ - !ruby/object:Gem::Dependency
124
+ name: csv
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ type: :runtime
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
123
137
  - !ruby/object:Gem::Dependency
124
138
  name: docx
125
139
  requirement: !ruby/object:Gem::Requirement
@@ -465,7 +479,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
465
479
  - !ruby/object:Gem::Version
466
480
  version: '0'
467
481
  requirements: []
468
- rubygems_version: 3.2.3
482
+ rubygems_version: 3.3.27
469
483
  signing_key:
470
484
  specification_version: 4
471
485
  summary: NDR Import