Purpose
Relaton for ASME provides a programmatic interface to fetch ASME standards and codes publications.
It accesses the ASME JSON API for publication listings and parses JSON-LD structured data from publication pages to extract complete bibliographic metadata.
Features
-
Fetching publication listings - Access ASME JSON API with pagination
-
Parsing publication metadata - Extract data from JSON-LD structured content
-
Data serialization - Export to JSON/YAML formats
-
Batch processing - Fetch multiple publications efficiently
-
Pre-scraped database - Access 4,928 ASME editions (1967-2025)
Architecture
General
RelatonAsme uses a two-stage data pipeline with object-oriented, model-driven architecture:
Stage 1: ASME JSON API
│
└─► IndexPage fetches from /api/products
│
└─► Returns publication URLs
│
▼
Stage 2: JSON-LD Parsing
│
└─► PublicationPage parses <script type="application/ld+json">
│
└─► Extracts Schema.org Product data
│
▼
Stage 3: Data Models
│
└─► AsmePublicationEdition (with URL, metadata, pricing)
Data model hierarchy
AsmePublication (Container)
│
└── AsmePublicationEdition[] (Primary Model - Array)
│
├── url: String (publication page URL)
├── document_type: String ("standard")
├── title: String (WITHOUT designator prefix)
├── document_identifier: String (e.g., "BPVC.I-2025")
├── designator: String (e.g., "BPVC.I")
├── edition_year: String (e.g., "2025")
├── publisher: String ("ASME")
├── publish_date: String
├── language: String ("EN")
├── number_of_pages: Integer (optional)
├── description: String (optional)
├── topics: String[] (optional)
└── formats: AsmeFormat[] (optional)
│
├── format_type: String (e.g., "PDF", "Print Book")
├── price: String (e.g., "$675.00")
└── isbn: String (optional)
Installation
Add this line to your application’s Gemfile:
gem "relaton-asme"
And then execute:
bundle install
Or install it yourself as:
gem install relaton-asme
Usage
Fetching publication listings
General
The IndexPage class fetches publication listings from the ASME JSON API at
https://www.asme.org/api/products.
Fetching publication URLs from API
Syntax:
index = RelatonAsme::Fetcher::IndexPage.new(
page_number: {page_number}, <b class="conum">(1)</b>
per_page: {per_page} <b class="conum">(2)</b>
)
urls = index.publication_urls <b class="conum">(3)</b>
-
Page number to fetch (1-based, default: 1)
-
Number of results per page (default: 100, max: 100)
-
Returns array of publication URLs
Where,
page_number-
The page number to fetch, starting from 1. Default is 1.
per_page-
Number of publications to fetch per page. Default is 100.
publication_urls-
Returns an array of publication URLs for each edition/format combination.
require "relaton_asme"
index = RelatonAsme::Fetcher::IndexPage.new(page_number: 1, per_page: 10)
urls = index.publication_urls
puts "Found #{urls.size} publication URLs"
urls.first(5).each { |url| puts url }
This queries the ASME API and returns URLs for each edition/format combination.
Example output:
Found 30 publication URLs
https://www.asme.org/codes-standards/find-codes-standards/bpvc-i-.../2025/print-book
https://www.asme.org/codes-standards/find-codes-standards/bpvc-i-.../2023/print-book
Parsing publication metadata
General
The PublicationPage class parses JSON-LD structured data from individual publication pages. Each page may contain multiple editions (different years) as separate offers.
Fetching publication data from JSON-LD
Syntax:
page = RelatonAsme::Fetcher::PublicationPage.new({url}) <b class="conum">(1)</b>
publication = page.to_data <b class="conum">(2)</b>
-
Publication URL to fetch
-
Returns
AsmePublicationobject with editions extracted from JSON-LD offers
Where,
url-
The full URL to the publication page on asme.org
to_data-
Returns an
AsmePublicationobject containing all editions from the page’s JSON-LD data
url = "https://www.asme.org/codes-standards/find-codes-standards/" \
"temperature-measurement/2024/pdf"
page = RelatonAsme::Fetcher::PublicationPage.new(url)
publication = page.to_data
if publication
publication.editions.each do |edition|
puts "Title: #{edition.title}"
puts "Year: #{edition.edition_year}"
puts "URL: #{edition.url}"
puts "Identifier: #{edition.document_identifier}"
end
end
This parses the JSON-LD structured data and may return multiple editions (e.g., 2024 and 1974 versions) from a single page.
Example output:
Title: Temperature Measurement (2024)
Year: 2024
URL: https://www.asme.org/.../2024/pdf/
Identifier: PTC 19.3-2024
Title: Temperature Measurement (1974)
Year: 1974
URL: https://www.asme.org/.../1974/pdf/
Identifier: PTC 19.3-1974
Batch processing with Runner
General
The Runner class orchestrates batch fetching of publications from the API.
Fetching all publications
Syntax:
runner = RelatonAsme::Fetcher::Runner.new <b class="conum">(1)</b>
editions = runner.fetch_all(
max_pages: {max_pages}, <b class="conum">(2)</b>
per_page: {per_page} <b class="conum">(3)</b>
)
-
Create a new runner instance
-
Maximum number of API pages to fetch (nil for all pages)
-
Number of publications per page (default: 100)
Where,
max_pages-
Optional limit on the number of API pages to process. Pass
nilto fetch all 671 publications (135 pages). per_page-
Number of publications to fetch per API page. Default is 100, maximum is 100.
editions-
Returns an array of
AsmePublicationEditionobjects from all fetched publications.
runner = RelatonAsme::Fetcher::Runner.new
editions = runner.fetch_all(max_pages: 2, per_page: 10)
puts "Fetched #{editions.size} editions"
editions.first(3).each do |edition|
puts "#{edition.document_identifier} - #{edition.title}"
end
This fetches publications from the first 2 API pages and parses their JSON-LD data.
Fetching and saving to file
Syntax:
runner = RelatonAsme::Fetcher::Runner.new
runner.fetch_all_editions(
{output_file}, <b class="conum">(1)</b>
format: {format}, <b class="conum">(2)</b>
max_pages: {max_pages} <b class="conum">(3)</b>
)
-
Path to output file
-
Output format (
:jsonor:yaml) -
Optional maximum number of pages
runner = RelatonAsme::Fetcher::Runner.new
runner.fetch_all_editions(
"asme_publications.yml",
format: :yaml,
max_pages: 1
)
This fetches publications from the first API page, parses their JSON-LD data,
and saves them as YAML to asme_publications.yml.
Data serialization
General
All data models support JSON and YAML serialization through lutaml-model.
Serializing to JSON
edition = RelatonAsme::Fetcher::AsmePublicationEdition.new(
url: "https://www.asme.org/...",
document_type: "standard",
title: "BPVC Section I",
document_identifier: "BPVC.I-2025",
designator: "BPVC.I",
edition_year: "2025",
publisher: "ASME",
publish_date: "2025",
language: "EN"
)
json = edition.to_json
puts json
Note: edition_year is a String, not an Integer.
Pre-scraped database
General
A complete database of ASME publications has been pre-scraped and is available in data/asme_publication_editions.yml.
Database contents
The database contains:
-
4,928 ASME publication editions
-
269 unique ASME publications
-
Year range: 1967 - 2025 (58 years)
-
Formats: Print Book, PDF, Bundle
Loading the database
require "yaml"
data = YAML.load_file(
"data/asme_publication_editions.yml",
permitted_classes: [Symbol]
)
puts "Loaded #{data.size} ASME editions"
# Find all editions for a specific designator
bpvc_editions = data.select { |e| e["designator"] == "BPVC.I" }
puts "BPVC.I has #{bpvc_editions.size} editions"
# Find editions by year
recent = data.select { |e| e["edition_year"].to_i >= 2020 }
puts "#{recent.size} editions from 2020 onwards"
Data model details
AsmePublicationEdition (Primary Model)
The primary data model containing all publication metadata for a specific edition.
| Attribute | Type | Description |
|---|---|---|
|
String |
Direct link to publication page on asme.org |
|
String |
Type of document (typically "standard") |
|
String |
Edition title WITHOUT designator prefix, with year in parentheses |
|
String |
Edition-specific identifier (e.g., "BPVC.I-2025") |
|
String |
ASME code/SKU (e.g., "BPVC.I", "B31.3", "Y14.5") |
|
String |
Publication year as string (e.g., "2025", "2023") |
|
String |
Publisher name (always "ASME") |
|
String |
Publication date (typically same as edition_year) |
|
String |
Language code (typically "EN") |
|
Integer |
Page count (optional, not available in JSON-LD) |
|
String |
Detailed description (optional, not available in JSON-LD) |
|
Array<String> |
Array of topic names (optional, not available in JSON-LD) |
|
Array<AsmeFormat> |
Available formats and pricing from JSON-LD offers |
AsmeFormat
Represents a publication format with pricing information extracted from JSON-LD offers.
| Attribute | Type | Description |
|---|---|---|
|
String |
Format type (e.g., "PDF", "Print Book", "Bundle") |
|
String |
Price formatted as string (e.g., "$675.00") |
|
String |
ISBN number if available (optional, not in JSON-LD) |
AsmePublication (Container)
Container model for grouping related publication editions.
| Attribute | Type | Description |
|---|---|---|
|
String |
Publication designator/SKU used for grouping |
|
Array<AsmePublicationEdition> |
Array of publication editions with different years/formats |
Development
After checking out the repo, run bundle install to install dependencies.
Run tests:
bundle exec rake spec
Run RuboCop:
bundle exec rake rubocop
Run all checks (tests + RuboCop):
bundle exec rake
Scraping ASME Publications
To scrape ASME publications and save to a file:
require "relaton_asme"
runner = RelatonAsme::Fetcher::Runner.new
# Fetch all publications (671 total, takes ~2 hours)
runner.fetch_all_editions(
"data/asme_publications.yml",
format: :yaml
)
# Or fetch just a few pages for testing
runner.fetch_all_editions(
"data/sample.yml",
format: :yaml,
max_pages: 2
)
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/relaton/relaton-asme.
Copyright & license
Copyright Ribose.
The gem is available as open source under the terms of the BSD-2-Clause License.