sepa_rator 1.3.1 → 2.0.0

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: 1f81f775b9672175eb25c887d1c4d31525b1b218e7e7c4efa36b372bb85010e0
4
- data.tar.gz: f64ce6a61f43c39f968bc17ead46ba48370351b440c32f838def6385dd719ca0
3
+ metadata.gz: 6a31b76a38e117f7875a90c25738f28ec1a433717e800e2225ceedf1c51797af
4
+ data.tar.gz: 292b6ad1c1ee43c026a4d51c4a3c48d93b7dd4dda50ce7d03f1f046400b83e25
5
5
  SHA512:
6
- metadata.gz: dc7867b7ecf3f7bd2e19bc0fb557e75d1fb5492cc4ad51b34162fd522e798f7befdc4b47af0d9f52ede7eb0368d154834399466bb1b59b2d70faf6166d1a4a33
7
- data.tar.gz: 8b3a5dfd400470eb34d62e263bf429ef4dc2d407ee5a2a7b9e69307c206374169b528f307bb729e1af0fb57c263f4de7cc83ce15c6427249e8333e0d078a3113
6
+ metadata.gz: c1a17fd1061cf8b46f0ce44df8a1914d6eac61fa1c9fa3c4176ca7149a1dab465493dd578796300204af46b9aa93263a452f35fcf6274d5716f2b825118d43b7
7
+ data.tar.gz: 8fd4c0a268f30e1a2915536b1f46485fa734b1eb2dd2e84e5a02d7759a44f8b3287c2e094c7a98b1d3dee125a019dc199dda3c3484ab764cffa5ca155a69df87
data/README.md CHANGED
@@ -34,15 +34,27 @@ For the full per-profile detail (XSD, constraints, capabilities), see [DOCUMENTA
34
34
 
35
35
  ## Requirements
36
36
 
37
- - Ruby 3.2+
37
+ - Ruby 3.2+ (tested up to 4.0)
38
38
  - ActiveModel 7.0+ (tested up to 8.1)
39
39
 
40
40
  ## Installation
41
41
 
42
42
  ```ruby
43
- gem 'sepa_rator', '~> 1.0'
43
+ gem 'sepa_rator', '~> 2.0'
44
44
  ```
45
45
 
46
+ ### Country-specific schemas
47
+
48
+ The core gem ships only the ISO baseline XSDs, which cover the ISO, EPC, CFONB, GB and NL profiles. Profiles validated against a national XSD variant need a companion gem:
49
+
50
+ | Profiles | Companion gem |
51
+ |---|---|
52
+ | `at.*` (PSA 🇦🇹) | `gem 'sepa_rator-at'` |
53
+ | `dk.*` (DK/GBIC 🇩🇪) | `gem 'sepa_rator-dk'` |
54
+ | `sps.*` (SPS 🇨🇭) | `gem 'sepa_rator-sps'` |
55
+
56
+ Bundler auto-requires them; no further setup needed. Without the gem, generating XML for such a profile raises a `SEPA::Error` naming the gem to add. Custom schema directories can also be registered with `SEPA.register_schema_root(path)`.
57
+
46
58
  ## Quick start
47
59
 
48
60
  ### The simplest possible Credit Transfer
@@ -6,15 +6,27 @@ module SEPA
6
6
  module SchemaValidation
7
7
  extend ActiveSupport::Concern
8
8
 
9
- SCHEMA_DIR = File.expand_path('../../schema', __dir__).freeze
10
- # Eagerly-initialised module-level XSD cache, shared across every
11
- # class that includes SchemaValidation. Keyed by `profile.xsd_path`
12
- # so two profiles that share an ISO schema name but point to
13
- # different XSD files (e.g. the ISO baseline and the DK GBIC5
14
- # variant) never share a cache entry.
9
+ DEFAULT_SCHEMA_ROOT = File.expand_path('../../schema', __dir__).freeze
10
+ # So missing-schema errors can name the companion gem to install.
11
+ SCHEMA_GEMS = { 'at' => 'sepa_rator-at', 'dk' => 'sepa_rator-dk', 'sps' => 'sepa_rator-sps' }.freeze
12
+ # Keyed by resolved absolute path so a late-registered root takes
13
+ # effect immediately.
15
14
  SCHEMA_CACHE = {} # rubocop:disable Style/MutableConstant -- intentional cache
16
15
  SCHEMA_CACHE_MUTEX = Mutex.new
17
16
 
17
+ class << self
18
+ def schema_roots
19
+ @schema_roots ||= [DEFAULT_SCHEMA_ROOT]
20
+ end
21
+
22
+ def register_schema_root(path)
23
+ expanded = File.expand_path(path)
24
+ raise ArgumentError, "register_schema_root: #{expanded} is not a directory" unless File.directory?(expanded)
25
+
26
+ schema_roots.unshift(expanded) unless schema_roots.include?(expanded)
27
+ end
28
+ end
29
+
18
30
  private
19
31
 
20
32
  def validate_final_document!(document, profile)
@@ -31,23 +43,34 @@ module SEPA
31
43
  end
32
44
 
33
45
  def load_xsd(profile)
34
- cache_key = profile.xsd_path
35
- cached = SCHEMA_CACHE[cache_key]
46
+ path = resolve_xsd_path(profile)
47
+ cached = SCHEMA_CACHE[path]
36
48
  return cached if cached
37
49
 
38
50
  SCHEMA_CACHE_MUTEX.synchronize do
39
- SCHEMA_CACHE[cache_key] ||= read_xsd(profile)
51
+ SCHEMA_CACHE[path] ||= read_xsd(path)
40
52
  end
41
53
  end
42
54
 
43
- def read_xsd(profile)
44
- path = File.join(SCHEMA_DIR, profile.xsd_path)
55
+ def resolve_xsd_path(profile)
56
+ SchemaValidation.schema_roots
57
+ .map { |root| File.join(root, profile.xsd_path) }
58
+ .find { |candidate| File.file?(candidate) } ||
59
+ raise_missing_schema!(profile)
60
+ end
61
+
62
+ def read_xsd(path)
45
63
  # File.open (not File.read) so Nokogiri can resolve xs:include/xs:redefine
46
64
  # relative to the XSD file's directory (needed for AT/PSA schemas).
47
65
  File.open(path) { |f| Nokogiri::XML::Schema(f) }
48
- rescue Errno::ENOENT => e
66
+ end
67
+
68
+ def raise_missing_schema!(profile)
69
+ gem_name = SCHEMA_GEMS[profile.xsd_path.split('/').first]
70
+ hint = gem_name ? " Add gem '#{gem_name}' to your Gemfile to validate profile #{profile.id}." : ''
49
71
  raise SEPA::Error,
50
- "[#{profile.id}] XSD file not found at #{path} (xsd_path=#{profile.xsd_path.inspect}): #{e.message}"
72
+ "[#{profile.id}] XSD file #{profile.xsd_path} not found " \
73
+ "(searched roots: #{SchemaValidation.schema_roots.join(', ')}).#{hint}"
51
74
  end
52
75
  end
53
76
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SEPA
4
- VERSION = '1.3.1'
4
+ VERSION = '2.0.0'
5
5
  end
data/lib/sepa_rator.rb CHANGED
@@ -76,3 +76,10 @@ require 'sepa_rator/profiles/nl'
76
76
 
77
77
  # Country defaults must load AFTER all variant profiles have been defined.
78
78
  require 'sepa_rator/profiles/country_defaults'
79
+
80
+ module SEPA
81
+ # Entry point for companion schema gems (sepa_rator-at, …) at require time.
82
+ def self.register_schema_root(path)
83
+ SchemaValidation.register_schema_root(path)
84
+ end
85
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sepa_rator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Georg Leciejewski
@@ -67,22 +67,6 @@ extra_rdoc_files: []
67
67
  files:
68
68
  - LICENSE.txt
69
69
  - README.md
70
- - lib/schema/at/pain.001.001.03.at.004.xsd
71
- - lib/schema/at/pain.001.001.03.xsd
72
- - lib/schema/at/pain.001.001.09.at.005.xsd
73
- - lib/schema/at/pain.001.001.09.xsd
74
- - lib/schema/at/pain.001.codelists.xsd
75
- - lib/schema/at/pain.001_codelists.xsd
76
- - lib/schema/at/pain.008.001.02.at.004.xsd
77
- - lib/schema/at/pain.008.001.02.xsd
78
- - lib/schema/at/pain.008.001.08.at.004.xsd
79
- - lib/schema/at/pain.008.001.08.xsd
80
- - lib/schema/at/pain.008.codelists.xsd
81
- - lib/schema/at/pain.008_codelists.xsd
82
- - lib/schema/dk/pain.001.001.03_GBIC_3.xsd
83
- - lib/schema/dk/pain.001.001.09_GBIC_5.xsd
84
- - lib/schema/dk/pain.008.001.02_GBIC_3.xsd
85
- - lib/schema/dk/pain.008.001.08_GBIC_5.xsd
86
70
  - lib/schema/iso/pain.001.001.03.xsd
87
71
  - lib/schema/iso/pain.001.001.09.xsd
88
72
  - lib/schema/iso/pain.001.001.13.xsd
@@ -93,8 +77,6 @@ files:
93
77
  - lib/schema/iso/pain.008.001.12.xsd
94
78
  - lib/schema/iso/pain.008.002.02.xsd
95
79
  - lib/schema/iso/pain.008.003.02.xsd
96
- - lib/schema/sps/pain.001.001.09.ch.03.xsd
97
- - lib/schema/sps/pain.008.001.02.chsdd.02.xsd
98
80
  - lib/sepa_rator.rb
99
81
  - lib/sepa_rator/account.rb
100
82
  - lib/sepa_rator/account/address.rb