relaton 3.0.0.pre.alpha.19 → 3.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: eee3114e443e307b96ca18a96dff2a48dcb4d5b5dae424fd2ecb3ca6e57202be
4
- data.tar.gz: 7208a6c3f058fca1874370a24bfe89d03516d5c4d66477d8c4160c4517717c44
3
+ metadata.gz: c749882e825411654761a8fa93aafe143cbcc9ff3f1ab2df213af541b423274b
4
+ data.tar.gz: 18424b0050827481d74048b45397610181e4b6b77f07b718bf9ab1fa589e6d6a
5
5
  SHA512:
6
- metadata.gz: f8c13c3bbdbe96caa0874d0b0c4671c05fa4c6652070372b0fc55992ac3c87834a6e03bda4a7fe17945d31db33b5f1a5a99d927d8d1d203d8238a7e837c29d77
7
- data.tar.gz: 3e5e49f9fdd82e5abe32bc4afb35b2baf075bc1b10aee9aad0e663f4361a0486069ff94cf3d4c066d17ccf4f32dacfac5eccad6eb1534008978d39734577dc84
6
+ metadata.gz: e37f88eb3fd9f0c20ae2db7bbb08fbcd54ae7b6784ab249494c39d6d56fa452940883ecb1ad5225ec27115ea6fe5a05c518ab1d143e28566a87c111d83ce2361
7
+ data.tar.gz: 79d5434ca258b521c473e88cd8afbd763bff52e10e46ce20ed8f3743679967bcf9cb51444eef9fd4cd21ceb11b32a830664e105eb92747378336aa91c2d63aa1
@@ -1,15 +1,10 @@
1
1
  module Relaton
2
2
  module Bib
3
3
  class Formattedref < LocalizedMarkedUpString
4
- attribute :format, :string
5
-
4
+ # No `format` attribute: the bibdata grammar dropped it (relaton-bib
5
+ # #94) — an ingested format= is silently dropped, never re-emitted.
6
6
  xml do
7
7
  root "formattedref"
8
- map_attribute "format", to: :format
9
- end
10
-
11
- key_value do
12
- map "format", to: :format
13
8
  end
14
9
 
15
10
  # Handle plain string input from YAML/JSON deserialization
@@ -35,7 +30,7 @@ module Relaton
35
30
  def self.simple_content?(instance, format)
36
31
  return false if format == :xml
37
32
 
38
- instance.format.nil? && instance.language.nil? &&
33
+ instance.language.nil? &&
39
34
  instance.script.nil? && instance.locale.nil?
40
35
  end
41
36
  end
@@ -23,10 +23,15 @@ module Relaton
23
23
  attribute :docnumber, :string
24
24
  attribute :date, Date, collection: true, initialize_empty: true
25
25
  attribute :contributor, Contributor, collection: true, initialize_empty: true
26
- # Lenient ingest: some upstream corpus documents carry more than one
27
- # <edition> in a bibitem (multi-edition bibdata, relaton-db#149); keep
28
- # the first instead of failing the whole round-trip with
29
- # CollectionTrueMissingError (lutaml-model#971, singular_tolerance).
26
+ # THE LAW: a bibitem has exactly one edition. A second <edition>
27
+ # element is always wrong output — in the one known case, the
28
+ # iso-10303 collection render fused the SMRL library bibdata (a
29
+ # different document that contains the parts) into part bibitems
30
+ # (relaton-db#149). The tolerance is a crash guard against that
31
+ # wrong output: it keeps the bibitem's own (leading) edition instead
32
+ # of aborting the round-trip with CollectionTrueMissingError
33
+ # (lutaml-model#971). The emitter fix is the real fix; this must
34
+ # never fire on correct data.
30
35
  attribute :edition, Edition, singular_tolerance: :first
31
36
  attribute :version, Version, collection: true, initialize_empty: true
32
37
  attribute :note, Note, collection: true, initialize_empty: true
@@ -32,4 +32,4 @@ Namespace: `Relaton::Bsi`. Retrieval flow:
32
32
 
33
33
  ## Testing
34
34
 
35
- RSpec with WebMock + VCR (cassettes in `spec/vcr_cassettes/`, record `:once`, 7-day re-record). Network is blocked via WebMock. No index fixture — BSI has no curated index; `spec/fixtures/` holds XML/YAML round-trip data.
35
+ RSpec with WebMock + VCR (cassettes in `spec/vcr_cassettes/`, record `:once`, never auto-rerecorded). Network is blocked via WebMock. No index fixture — BSI has no curated index; `spec/fixtures/` holds XML/YAML round-trip data.
@@ -193,7 +193,7 @@ The `:supplement_year` exclude key is a different thing and stays.
193
193
 
194
194
  ## Testing
195
195
 
196
- RSpec with WebMock + VCR (cassettes in `spec/vcr_cassettes/`, record `:once`, 7-day re-record). Network is blocked via WebMock. No index fixture — CEN is scraped, not indexed; `spec/fixtures/` holds XML/YAML round-trip data. The scraper is inherently brittle to portal HTML changes.
196
+ RSpec with WebMock + VCR (cassettes in `spec/vcr_cassettes/`, record `:once`, never auto-rerecorded). Network is blocked via WebMock. No index fixture — CEN is scraped, not indexed; `spec/fixtures/` holds XML/YAML round-trip data. The scraper is inherently brittle to portal HTML changes.
197
197
 
198
198
  - `spec/cen/relaton/cen/docidentifier_spec.rb` unit-tests the three mutators over
199
199
  every identifier form the portal serves, including the two rows above that the
@@ -36,7 +36,7 @@ Key classes in `lib/relaton/doi/`:
36
36
  ## Test Setup
37
37
 
38
38
  - **RSpec** with `expect` syntax only (monkey patching disabled)
39
- - **VCR** cassettes in `spec/vcr_cassettes/` record Crossref HTTP responses, re-recorded every 7 days on purpose (see root `CLAUDE.md`). Because Crossref rate-limits, **re-record this suite alone** — under parallel `rake spec` it answers 429 and the empty body gets recorded as if it were data.
39
+ - **VCR** cassettes in `spec/vcr_cassettes/` record Crossref HTTP responses and are never auto-rerecorded (see root `CLAUDE.md`). Because Crossref rate-limits, **re-record this suite alone** — under parallel `rake spec` it answers 429 and the empty body gets recorded as if it were data.
40
40
  - **XML fixtures** in `spec/fixtures/` — expected output XML files. The `read_fixture` helper auto-substitutes today's date into `<fetched>` tags.
41
41
  - **equivalent-xml** gem for XML comparison in integration tests
42
42
  - Integration tests in `spec/relaton/doi_spec.rb` cover 40+ document types via VCR cassettes
@@ -54,7 +54,8 @@ bin/console
54
54
  4. Search matches against `:id` field (string comparison via `include?` or custom block)
55
55
  5. `save` writes index as YAML to local file
56
56
 
57
- With `pages_url:` (W3C, the #189 pilot) steps 2–3 change: a non-String query
57
+ With `pages_url:` (#189; W3C piloted it, and every indexed flavor's consumer
58
+ now uses it except JIS, NIST and Plateau, which still read the zip) steps 2–3 change: a non-String query
58
59
  goes to `ShardSource#rows` and reads one shard, and `Type#index` (a String query,
59
60
  a block-only search) is `ShardSource#whole_index`, the `<index>.zip` that the
60
61
  manifest names, read from the Pages site. No `FileIO#read`, no disk cache.
@@ -172,8 +173,8 @@ the same arguments:
172
173
  | call site | `url:` | `pubid_class:` |
173
174
  |---|---|---|
174
175
  | producer — `DataFetcher#index` | none (`file:` is CWD-relative) | **yes** — `FileIO#save` calls `to_hash` only for instances of it |
175
- | consumer — `Bibliography`/`HitCollection#index` | the published `.zip` | **yes** — without it the rows stay raw hashes and `Type#search` stops narrowing |
176
- | consumer on the Pages shards (W3C) | none; **`pages_url:`** | **yes** — a shard row is deserialized with it |
176
+ | consumer on the zip (JIS, NIST, Plateau) — `Bibliography`/`HitCollection#index` | the published `.zip` | **yes** — without it the rows stay raw hashes and `Type#search` stops narrowing |
177
+ | consumer on the Pages shards (all other indexed flavors) | none; **`pages_url:`** | **yes** — a shard row is deserialized with it |
177
178
  | delete — `Processor#remove_index_file` | **`true`** | **no** |
178
179
 
179
180
  The delete path is `Type#remove_file` → `FileIO#remove` →
@@ -308,14 +308,21 @@ module Relaton
308
308
  end
309
309
 
310
310
  # The query is the reference, so two identifiers take the subset match.
311
- # See #search for the exact-equality escape hatch.
311
+ # See #search for the exact-equality escape hatch. A dated base query
312
+ # also resolves a wrapped record of exactly that edition (pubid#580's
313
+ # ruling): the undated query is the family wildcard, so the dated one
314
+ # names one edition, and the record embodying it answers through
315
+ # pubid's wrapped_edition_of? even when its printed identity is one
316
+ # level down ("IEC CA 01:2020" → the CSV wrapper).
312
317
  def match_item(item, id)
313
318
  if item[:id].is_a?(String)
314
319
  item[:id].include?(id.is_a?(String) ? id : id.to_s)
315
320
  elsif id.is_a?(String)
316
321
  item[:id].to_s.include?(id)
317
322
  else
318
- id === item[:id]
323
+ id === item[:id] ||
324
+ (item[:id].is_a?(::Pubid::Identifier) &&
325
+ item[:id].wrapped_edition_of?(id))
319
326
  end
320
327
  end
321
328
  end
@@ -36,7 +36,7 @@ Uses `Relaton::Bib::` namespace (not the old `RelatonBib::`). Key classes: `Item
36
36
 
37
37
  ## Testing
38
38
 
39
- - **VCR** records HTTP interactions in `spec/vcr_cassettes/` (re-records every 7 days)
39
+ - **VCR** records HTTP interactions in `spec/vcr_cassettes/` (never auto-rerecorded; re-record deliberately)
40
40
  - **WebMock** disables real HTTP by default
41
41
  - **SimpleCov** tracks coverage
42
42
  - Fixtures in `spec/fixtures/`
@@ -35,4 +35,4 @@ Key dependency: `pubid-iso` gem handles ISO publication identifier parsing and c
35
35
  - **Framework:** RSpec with VCR cassettes and WebMock
36
36
  - **Network access:** fully blocked via `WebMock.disable_net_connect!`
37
37
  - **Index fixture:** `spec/fixtures/index-v1.zip` is pre-loaded into `Relaton::Index` pool in `before(:suite)` (configured in `spec/support/webmock.rb`). Run `rake spec:update_index` to refresh from relaton-data-iso.
38
- - **VCR:** cassettes in `spec/vcr_cassettes/`, record mode `:once`, re-record interval 7 days. Index download requests are ignored by VCR (handled by fixture instead).
38
+ - **VCR:** cassettes in `spec/vcr_cassettes/`, record mode `:once`, never auto-rerecorded (`re_record_interval: nil`). Index download requests are ignored by VCR (handled by fixture instead).
@@ -646,8 +646,8 @@ is gone (see **Runtime lookup**).
646
646
  `spec/itu/vcr_cassettes/itu_r_re*` cassettes back `data_crawler_r_spec.rb`, and
647
647
  each is owned by **exactly one example**. That is not stylistic: VCR re-records
648
648
  per cassette *insertion*, so a cassette shared across several examples is
649
- truncated to the first example's requests the moment the 7-day
650
- `re_record_interval` fires (verified — `itu_r_rec_bo` went 10 interactions → 1
649
+ truncated to the first example's requests the moment it is re-recorded
650
+ (verified — `itu_r_rec_bo` went 10 interactions → 1
651
651
  and took 15 examples down with it). If you add a crawler example, give it its
652
652
  own cassette rather than reusing one.
653
653
 
@@ -667,7 +667,7 @@ is gone (see **Runtime lookup**).
667
667
  responses. VCR ignores only `index-v2.zip` (the index comes from the fixture
668
668
  above), so the per-record `raw.githubusercontent.com/…/data/*.yaml` GETs **are**
669
669
  recorded. Re-record by deleting the file and running the suite with network
670
- access; `re_record_interval` is 7 days, so a stale-cassette run refreshes them.
670
+ access. `re_record_interval` is nil, so a cassette never refreshes by itself.
671
671
  - **Coverage:** SimpleCov, target near 100%
672
672
 
673
673
  Round-trip tests (serialize → deserialize → compare) are the primary pattern for model classes.
@@ -135,19 +135,16 @@ errors = schema.validate(file)
135
135
  ### HTTP Recording
136
136
 
137
137
  Tests use VCR with WebMock. Cassettes are stored in `spec/vcr_cassettes/` and
138
- `spec/support/vcr.rb` sets `record: :once` **with `re_record_interval: 7 days`**.
139
-
140
- **Gotcha (this bites periodically):** once a cassette is older than 7 days, the
141
- next run **re-records it from the live network** — so the suite is not truly
142
- deterministic. Two known failure modes when that fires: the NIST GitHub source
143
- data can drift (an author renamed, a `loc.gov` `identifier` dropped) so the
144
- round-tripped XML no longer matches the on-disk `spec/fixtures/*.xml` fixtures;
145
- and any flavor whose upstream throttles the recorder records a bad response.
146
- When cassettes show up mass-modified in `git status` for no code reason, that's
147
- the 7-day re-record firing, not a manual change. To recover: re-record cleanly
148
- (delete the stale cassette, run the spec) and, for the integration fixtures that
149
- compare full XML (`get.xml`, `hit.xml`, `hit_bibitem.xml`), regenerate them
150
- (delete → the spec rewrites them via `File.write … unless File.exist?`).
138
+ `spec/support/vcr.rb` sets `record: :once` with `re_record_interval: nil`, so a
139
+ cassette replays as committed and never re-records by itself (relaton#360).
140
+
141
+ **When you re-record deliberately:** the NIST GitHub source data can drift (an
142
+ author renamed, a `loc.gov` `identifier` dropped), so the round-tripped XML no
143
+ longer matches the on-disk `spec/fixtures/*.xml` fixtures; and an upstream that
144
+ throttles the recorder records a bad response. Delete the stale cassette, run
145
+ the spec, and, for the integration fixtures that compare full XML (`get.xml`,
146
+ `hit.xml`, `hit_bibitem.xml`), regenerate them (delete → the spec rewrites them
147
+ via `File.write … unless File.exist?`) and read the diff.
151
148
 
152
149
  ### Test Data Stubbing
153
150
 
@@ -1,3 +1,3 @@
1
1
  module Relaton
2
- VERSION = "3.0.0.pre.alpha.19".freeze
2
+ VERSION = "3.0.0".freeze
3
3
  end
@@ -323,7 +323,7 @@ Tests use [Jing](https://github.com/jing-trang/jing-trang) for RelaxNG validatio
323
323
  Tests use RSpec with:
324
324
  - **Round-trip tests** — YAML/XML → object → YAML/XML, verifying lossless serialization
325
325
  - **Schema validation** — XML output validated against `grammars/relaton-w3c-compile.rng`
326
- - **VCR** — recorded HTTP cassettes in `spec/vcr_cassettes/` (7-day re-record interval)
326
+ - **VCR** — recorded HTTP cassettes in `spec/vcr_cassettes/` (never auto-rerecorded; re-record deliberately)
327
327
  - **WebMock** — disables external HTTP in tests
328
328
 
329
329
  Test fixtures live in `spec/fixtures/` (YAML and XML files).
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relaton
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.pre.alpha.19
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-25 00:00:00.000000000 Z
11
+ date: 2026-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -442,14 +442,14 @@ dependencies:
442
442
  requirements:
443
443
  - - "~>"
444
444
  - !ruby/object:Gem::Version
445
- version: 2.0.0.pre.alpha.59
445
+ version: 2.0.0.pre.alpha.62
446
446
  type: :runtime
447
447
  prerelease: false
448
448
  version_requirements: !ruby/object:Gem::Requirement
449
449
  requirements:
450
450
  - - "~>"
451
451
  - !ruby/object:Gem::Version
452
- version: 2.0.0.pre.alpha.59
452
+ version: 2.0.0.pre.alpha.62
453
453
  - !ruby/object:Gem::Dependency
454
454
  name: yeptris
455
455
  requirement: !ruby/object:Gem::Requirement