ndr_support 5.10.0 → 5.10.2

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: 452da481cc47dceb02b62e7eb832db07ba61985fb2cdc8267a40b6194d0ef108
4
- data.tar.gz: e06b9a9845389b639c2fbe55aab1f4008d6dad69843a24113bf55b2b88fd7d56
3
+ metadata.gz: fbbca09887dac304f0a29b687893c47c70ae8b7bd600a646baa1f2d8a3d0e13f
4
+ data.tar.gz: e162d4c2ca88fe68c4f6a6e0af88d9d86b69e409fe5d7fbe8b72daec4d6ac516
5
5
  SHA512:
6
- metadata.gz: 7d06a0fb2e4adae1cbc71b7e89fd4fc45b527a419ad313d6440dd199ddb845df637b4dd505dce4220dae16bc6f059e96a2faddc455c1901a54bd8acba86b4b3e
7
- data.tar.gz: d5abcaa621cf18823123cd1241a519c2c2a9dd856ac6659a9f4d4497adcd11ec4b57beeade25c7e799b9924de02736344b91ef079b2bef5a65785a41a6d20333
6
+ metadata.gz: dd29e398e40a4eee8ad4da3ad27421a92fc1587f10b96334b981b97de9796961850101132c6fa37389b748b5cb5bad285f7bf6ba736dff47c104ff2cf86e5465
7
+ data.tar.gz: '059894e4a5a942d7f4a158fa82f8df14ec0f8899eae140ebcabf3d9235209301ad750f9659d7e6e87eecf236a2aaa35af92703025be3a6f189354cac241f75dd'
data/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  ## [Unreleased]
2
2
  * No unreleased changes
3
3
 
4
+ ## 5.10.2 / 2024-02-09
5
+ ## Fixed
6
+ * Refactored the cleaning code to fix Rubcocop issues
7
+
8
+ ## Added
9
+ * Added a new 'log10' cleaning method
10
+
11
+ ## 5.10.1 / 2024-01-04
12
+ ## Fixed
13
+ * Add 2026 bank holidays
14
+ * Allow YAML aliases when using `yaml_safe_classes`
15
+
4
16
  ## 5.10.0 / 2023-11-17
5
17
  ## Changed
6
18
  * Generate UTF-8 encoded YAML by default. Disable with `utf8_storage = false`
data/code_safety.yml CHANGED
@@ -23,7 +23,7 @@ file safety:
23
23
  CHANGELOG.md:
24
24
  comments:
25
25
  reviewed_by: brian.shand
26
- safe_revision: 646eaebdf824490150e991225f9e15abb67dd4c1
26
+ safe_revision: af6c7ddedf6627de8ec823ff33399c7938cd64b1
27
27
  CODE_OF_CONDUCT.md:
28
28
  comments:
29
29
  reviewed_by: timgentry
@@ -71,7 +71,7 @@ file safety:
71
71
  lib/ndr_support/concerns/working_days.rb:
72
72
  comments:
73
73
  reviewed_by: brian.shand
74
- safe_revision: bac214f4c93d8753268825408fc560171fac91c0
74
+ safe_revision: 6fb8c080befbb9c741c2bc3a2fadb29fe1c3d0aa
75
75
  lib/ndr_support/date_and_time_extensions.rb:
76
76
  comments:
77
77
  reviewed_by: brian.shand
@@ -136,10 +136,14 @@ file safety:
136
136
  comments:
137
137
  reviewed_by: brian.shand
138
138
  safe_revision: f4f7cb0803ea34a2f1ba83495d8bcbd942786bce
139
+ lib/ndr_support/string/clean_methodable.rb:
140
+ comments:
141
+ reviewed_by: brian.shand
142
+ safe_revision: af6c7ddedf6627de8ec823ff33399c7938cd64b1
139
143
  lib/ndr_support/string/cleaning.rb:
140
144
  comments:
141
- reviewed_by: brianshand
142
- safe_revision: b7b033ad9773cc9037c408a7763b113d31cbf191
145
+ reviewed_by: brian.shand
146
+ safe_revision: af6c7ddedf6627de8ec823ff33399c7938cd64b1
143
147
  lib/ndr_support/string/conversions.rb:
144
148
  comments:
145
149
  reviewed_by: brian.shand
@@ -171,7 +175,7 @@ file safety:
171
175
  lib/ndr_support/version.rb:
172
176
  comments:
173
177
  reviewed_by: brian.shand
174
- safe_revision: 765520ebaf3652bed7105995c815afe681dd5363
178
+ safe_revision: a58c1057a2829284ae527bdd66401b1891f28196
175
179
  lib/ndr_support/working_days.rb:
176
180
  comments:
177
181
  reviewed_by: josh.pencheon
@@ -179,7 +183,7 @@ file safety:
179
183
  lib/ndr_support/yaml/serialization_migration.rb:
180
184
  comments:
181
185
  reviewed_by: brian.shand
182
- safe_revision: 646eaebdf824490150e991225f9e15abb67dd4c1
186
+ safe_revision: c764a4d8c251b5076ed3d60391c8271bb5a099bc
183
187
  ndr_support.gemspec:
184
188
  comments:
185
189
  reviewed_by: brian.shand
@@ -254,8 +258,8 @@ file safety:
254
258
  safe_revision: b562d0c15ff1b1d565522a47e6bae47ea09706f0
255
259
  test/string/cleaning_test.rb:
256
260
  comments:
257
- reviewed_by: brianshand
258
- safe_revision: b7b033ad9773cc9037c408a7763b113d31cbf191
261
+ reviewed_by: brian.shand
262
+ safe_revision: af6c7ddedf6627de8ec823ff33399c7938cd64b1
259
263
  test/string/conversions_test.rb:
260
264
  comments:
261
265
  reviewed_by: brian.shand
@@ -283,4 +287,4 @@ file safety:
283
287
  test/yaml/serialization_test.rb:
284
288
  comments:
285
289
  reviewed_by: brian.shand
286
- safe_revision: 646eaebdf824490150e991225f9e15abb67dd4c1
290
+ safe_revision: c764a4d8c251b5076ed3d60391c8271bb5a099bc
@@ -136,6 +136,15 @@ module WorkingDays
136
136
  '2025-08-25', # Monday - Summer bank holiday
137
137
  '2025-12-25', # Thursday - Christmas Day
138
138
  '2025-12-26', # Friday - Boxing Day
139
+ # 2026
140
+ '2026-01-01', # Thursday - New Year’s Day
141
+ '2026-04-03', # Friday - Good Friday
142
+ '2026-04-06', # Monday - Easter Monday
143
+ '2026-05-04', # Monday - Early May bank holiday
144
+ '2026-05-25', # Monday - Spring bank holiday
145
+ '2026-08-31', # Monday - Summer bank holiday
146
+ '2026-12-25', # Friday - Christmas Day
147
+ '2026-12-28', # Monday - Boxing Day
139
148
  ].map { |str| Date.parse(str) }
140
149
 
141
150
  def self.check_lookup
@@ -0,0 +1,149 @@
1
+ # Adds the 'clean' method to String, which can be used to clean strings in various ways
2
+ # depending on the contents
3
+ module CleanMethodable
4
+ extend ActiveSupport::Concern
5
+
6
+ CLEAN_METHODS = {
7
+ nhsnumber: :clean_nhsnumber,
8
+ postcode: :clean_postcode, get_postcode: :clean_postcode,
9
+ lpi: :clean_lpi,
10
+ gender: :clean_gender, sex: :clean_sex, sex_c: :clean_sex_c,
11
+ name: :clean_name,
12
+ ethniccategory: :clean_ethniccategory,
13
+ code: :clean_code, code_icd: :clean_code_icd, icd: :clean_icd,
14
+ code_opcs: :clean_code_opcs,
15
+ hospitalnumber: :clean_hospitalnumber,
16
+ xmlsafe: :clean_xmlsafe, make_xml_safe: :clean_xmlsafe,
17
+ roman5: :clean_roman5,
18
+ tnmcategory: :clean_tnmcategory,
19
+ strip: :strip, upcase: :upcase, itself: :itself,
20
+ log10: :clean_log10
21
+ }.freeze
22
+
23
+ def clean(what)
24
+ cleaning_method = CLEAN_METHODS[what]
25
+ return send(cleaning_method) if cleaning_method
26
+
27
+ gsub(' ?', ' ')
28
+ end
29
+
30
+ private
31
+
32
+ def clean_nhsnumber
33
+ delete('^0-9')[0..9]
34
+ end
35
+
36
+ def clean_postcode
37
+ postcodeize(:db)
38
+ end
39
+
40
+ def clean_lpi
41
+ upcase.delete('^0-9A-Z')
42
+ end
43
+
44
+ def clean_gender
45
+ return '1' if self =~ /\AM(ale)?/i
46
+ return '2' if self =~ /\AF(emale)?/i
47
+
48
+ self
49
+ end
50
+
51
+ def clean_sex
52
+ # SECURE: BNS 2012-10-09: But may behave oddly for multi-line input
53
+ return '1' if self =~ /^M|1/i
54
+ return '2' if self =~ /^F|2/i
55
+
56
+ '0'
57
+ end
58
+
59
+ def clean_sex_c
60
+ return 'M' if self =~ /^M|1/i
61
+ return 'F' if self =~ /^F|2/i
62
+
63
+ ''
64
+ end
65
+
66
+ def clean_name
67
+ substitutions = {
68
+ '.' => '',
69
+ /,|;/ => ' ',
70
+ /\s{2,}/ => ' ',
71
+ '`' => '\''
72
+ }
73
+ substitutions.inject(upcase) { |a, e| a.gsub(*e) }.strip
74
+ end
75
+
76
+ def clean_ethniccategory
77
+ replace_ethniccategory = {
78
+ '0' => '0', '1' => 'M', '2' => 'N',
79
+ '3' => 'H', '4' => 'J', '5' => 'K',
80
+ '6' => 'R', '7' => '8', '&' => 'X',
81
+ ' ' => 'X', '99' => 'X'
82
+ }
83
+ replace_ethniccategory[self] || upcase
84
+ end
85
+
86
+ def clean_code
87
+ split_on_separators.map do |code|
88
+ code.blank? ? next : code.delete('.')
89
+ end.compact.join(' ')
90
+ end
91
+
92
+ def clean_code_icd
93
+ warn '[DEPRECATION] clean(:code_icd) is deprecated - consider using clean(:icd) instead.'
94
+ # regexp = /[A-Z][0-9]{2}(\.(X|[0-9]{1,2})|[0-9]?)( *(D|A)( |,|;|$))/
95
+ codes = upcase.split_on_separators.delete_if { |x| x.squash.blank? }
96
+ cleaned_codes = []
97
+ codes.each do |code|
98
+ if %w[A D].include?(code)
99
+ cleaned_codes[-1] += code
100
+ else
101
+ cleaned_codes << code
102
+ end
103
+ end
104
+ cleaned_codes.join(' ')
105
+ end
106
+
107
+ def clean_icd
108
+ codes = upcase.squish.split_on_separators.reject(&:blank?)
109
+ codes.map { |code| code.gsub(/(?<=\d)(\.?X?)/, '') }.join(' ')
110
+ end
111
+
112
+ def clean_hospitalnumber
113
+ self[-1..] =~ /\d/ ? self : self[0..-2]
114
+ end
115
+
116
+ def clean_xmlsafe
117
+ strip_xml_unsafe_characters
118
+ end
119
+
120
+ def clean_roman5
121
+ # This deromanises roman numerals between 1 and 5
122
+ gsub(/[IV]+/i) { |match| ROMAN_ONE_TO_FIVE_MAPPING[match.upcase] }
123
+ end
124
+
125
+ def clean_tnmcategory
126
+ sub!(/\A[tnm]/i, '')
127
+ if self =~ /\Ax\z/i
128
+ upcase
129
+ else
130
+ downcase
131
+ end
132
+ end
133
+
134
+ def clean_code_opcs
135
+ split_on_separators.map do |code|
136
+ db_code = code.squash
137
+ next unless 4 == db_code.length || db_code =~ /CZ00[12]/
138
+
139
+ db_code
140
+ end.compact.join(' ')
141
+ end
142
+
143
+ def clean_log10
144
+ f_value = Float(self, exception: false)
145
+ return self if f_value.nil? || f_value.negative?
146
+
147
+ f_value.zero? ? '0.0' : Math.log10(f_value).to_s
148
+ end
149
+ end
@@ -1,6 +1,11 @@
1
1
  require 'active_support/core_ext/string/filters'
2
+ require 'ndr_support/string/clean_methodable'
2
3
 
4
+ # Extends String clean with various methods of cleaning strings
5
+ # zand polishing them
3
6
  class String
7
+ include CleanMethodable
8
+
4
9
  INVALID_CONTROL_CHARS = /[\x00-\x08\x0b-\x0c\x0e-\x1f]/
5
10
  ROMAN_ONE_TO_FIVE_MAPPING = { 'I' => '1', 'II' => '2', 'III' => '3', 'IIII' => '4', 'IV' => '4', 'V' => '5' }
6
11
 
@@ -26,9 +31,8 @@ class String
26
31
  # Parameter "option" can be :user, :compact, :db
27
32
  def postcodeize(option = :user)
28
33
  nspce = gsub(/[[:space:]]/, '').upcase
29
- unless nspce.blank? || POSTCODE_REGEXP =~ nspce
30
- return self # Don't change old-style or malformed postcodes
31
- end
34
+ return self unless nspce.blank? || POSTCODE_REGEXP =~ nspce # Don't change old-style or malformed postcodes
35
+
32
36
  case option
33
37
  when :compact
34
38
  nspce
@@ -43,106 +47,6 @@ class String
43
47
  end
44
48
  end
45
49
 
46
- def clean(what)
47
- case what
48
- when :nhsnumber
49
- delete('^0-9')[0..9]
50
- when :postcode, :get_postcode
51
- postcodeize(:db)
52
- when :lpi
53
- upcase.delete('^0-9A-Z')
54
- when :gender
55
- if self =~ /\AM(ale)?/i
56
- '1'
57
- elsif self =~ /\AF(emale)?/i
58
- '2'
59
- else
60
- self
61
- end
62
- when :sex
63
- # SECURE: BNS 2012-10-09: But may behave oddly for multi-line input
64
- if self =~ /^M|1/i
65
- '1'
66
- elsif self =~ /^F|2/i
67
- '2'
68
- else
69
- '0'
70
- end
71
- when :sex_c
72
- if self =~ /^M|1/i
73
- 'M'
74
- elsif self =~ /^F|2/i
75
- 'F'
76
- else
77
- ''
78
- end
79
- when :name
80
- substitutions = {
81
- '.' => '',
82
- /,|;/ => ' ',
83
- /\s{2,}/ => ' ',
84
- '`' => '\''
85
- }
86
- substitutions.inject(upcase) { |a, e| a.gsub(*e) }.strip
87
- when :ethniccategory
88
- replace_ethniccategory = {
89
- '0' => '0',
90
- '1' => 'M',
91
- '2' => 'N',
92
- '3' => 'H',
93
- '4' => 'J',
94
- '5' => 'K',
95
- '6' => 'R',
96
- '7' => '8',
97
- '&' => 'X',
98
- ' ' => 'X',
99
- '99' => 'X'
100
- }
101
- replace_ethniccategory[self] || upcase
102
- when :code
103
- split_on_separators.map do |code|
104
- code.blank? ? next : code.delete('.')
105
- end.compact.join(' ')
106
- when :code_icd
107
- warn '[DEPRECATION] clean(:code_icd) is deprecated - consider using clean(:icd) instead.'
108
- # regexp = /[A-Z][0-9]{2}(\.(X|[0-9]{1,2})|[0-9]?)( *(D|A)( |,|;|$))/
109
- codes = upcase.split_on_separators.delete_if { |x| x.squash.blank? }
110
- cleaned_codes = []
111
- codes.each do |code|
112
- if code == 'D' || code == 'A'
113
- cleaned_codes[-1] += code
114
- else
115
- cleaned_codes << code
116
- end
117
- end
118
- cleaned_codes.join(' ')
119
- when :icd
120
- codes = upcase.squish.split_on_separators.reject(&:blank?)
121
- codes.map { |code| code.gsub(/(?<=\d)(\.?X?)/, '') }.join(' ')
122
- when :code_opcs
123
- clean_code_opcs
124
- when :hospitalnumber
125
- self[-1..-1] =~ /\d/ ? self : self[0..-2]
126
- when :xmlsafe, :make_xml_safe
127
- strip_xml_unsafe_characters
128
- when :roman5
129
- # This deromanises roman numerals between 1 and 5
130
- gsub(/[IV]+/i) { |match| ROMAN_ONE_TO_FIVE_MAPPING[match.upcase] }
131
- when :tnmcategory
132
- sub!(/\A[tnm]/i, '')
133
- if self =~ /\Ax\z/i
134
- upcase
135
- else
136
- downcase
137
- end
138
- when :strip, :upcase, :itself
139
- # SECURE: 14-06-2017 TPG Fixed list of executable methods (whats)
140
- send(what)
141
- else
142
- gsub(' ?', ' ')
143
- end
144
- end
145
-
146
50
  def strip_xml_unsafe_characters
147
51
  gsub(String::INVALID_CONTROL_CHARS, '')
148
52
  end
@@ -156,14 +60,4 @@ class String
156
60
  def split_on_separators(regexp = / |,|;/)
157
61
  split(regexp)
158
62
  end
159
-
160
- private
161
-
162
- def clean_code_opcs
163
- split_on_separators.map do |code|
164
- db_code = code.squash
165
- next unless 4 == db_code.length || db_code =~ /CZ00[12]/
166
- db_code
167
- end.compact.join(' ')
168
- end
169
63
  end
@@ -3,5 +3,5 @@
3
3
  # This defines the NdrSupport version. If you change it, rebuild and commit the gem.
4
4
  # Use "rake build" to build the gem, see rake -T for all bundler rake tasks.
5
5
  module NdrSupport
6
- VERSION = '5.10.0'
6
+ VERSION = '5.10.2'
7
7
  end
@@ -43,13 +43,11 @@ module NdrSupport
43
43
 
44
44
  # TODO: Bump NdrSupport major version, and switch to safe_load by default
45
45
  object = if yaml_safe_classes == :unsafe
46
- unless Psych::VERSION.start_with?('3.')
47
- raise(SecurityError, 'Unsafe YAML no longer supported')
48
- end
46
+ raise(SecurityError, 'Unsafe YAML no longer supported') unless Psych::VERSION.start_with?('3.')
49
47
 
50
48
  Psych.load(string)
51
49
  else
52
- Psych.safe_load(string, permitted_classes: yaml_safe_classes)
50
+ Psych.safe_load(string, permitted_classes: yaml_safe_classes, aliases: true)
53
51
  end
54
52
 
55
53
  # Ensure that any string related to the object
@@ -30,6 +30,12 @@ class String
30
30
  assert_equal 'IP222', 'IP222'.postcodeize(:db)
31
31
  assert_equal 'IP222E', 'IP222E'.postcodeize(:db)
32
32
  assert_equal 'HANTS', 'HANTS'.postcodeize(:db)
33
+ # Log10
34
+ assert_equal '0.0', '0'.clean(:log10)
35
+ assert_equal '-10.1', '-10.1'.clean(:log10)
36
+ assert_match(/\A0.041392685158225[0-9]*\z/, '1.1'.clean(:log10),
37
+ "Different ruby versions give '0.04139268515822507' or '0.04139268515822508'")
38
+ assert_equal 'BILBO', 'BILBO'.clean(:log10)
33
39
  end
34
40
 
35
41
  test 'xml_unsafe?' do
@@ -153,7 +159,8 @@ class String
153
159
  end
154
160
 
155
161
  test 'clean code_icd' do
156
- # TODO
162
+ assert_equal 'C449 Q123A Q455', 'C449,Q123,A,Q455'.clean(:code_icd)
163
+ assert_equal 'C449 Q123D Q455', 'C449,Q123,D,Q455'.clean(:code_icd)
157
164
  end
158
165
 
159
166
  test 'clean icd' do
@@ -8,6 +8,14 @@ class SerializationTest < Minitest::Test
8
8
  assert_equal hash, load_yaml(dump_yaml(hash))
9
9
  end
10
10
 
11
+ test 'should support aliases correctly' do
12
+ x = { 'c' => 5 }
13
+ hash = { 'a' => x, 'b' => x }
14
+ hash_yaml = "---\na: &1\n c: 5\nb: *1\n"
15
+ assert_equal hash, load_yaml(hash_yaml), 'Deserialising known YAML with an alias'
16
+ assert_equal hash, load_yaml(dump_yaml(hash)), 'Deserialising a structure with repeated objects'
17
+ end
18
+
11
19
  test 'should handle syck-encoded characters' do
12
20
  assert_syck_1_8_yaml_loads_correctly
13
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ndr_support
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.10.0
4
+ version: 5.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - NCRS Development Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-17 00:00:00.000000000 Z
11
+ date: 2024-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -242,6 +242,7 @@ files:
242
242
  - lib/ndr_support/regexp_range.rb
243
243
  - lib/ndr_support/safe_file.rb
244
244
  - lib/ndr_support/safe_path.rb
245
+ - lib/ndr_support/string/clean_methodable.rb
245
246
  - lib/ndr_support/string/cleaning.rb
246
247
  - lib/ndr_support/string/conversions.rb
247
248
  - lib/ndr_support/tasks.rb