Class: Oembed::ProductProvider
- Inherits:
-
Object
- Object
- Oembed::ProductProvider
- Defined in:
- app/services/oembed/product_provider.rb
Overview
Service object: product provider.
Defined Under Namespace
Classes: ProductNotFoundError, ProductUnavailableError
Class Method Summary collapse
-
.curl_typographic_quotes(text) ⇒ String
Convert straight ASCII quotes to curly typographic quotes per the project's curly-quote convention (https://typographyforlawyers.com/straight-and-curly-quotes.html).
-
.sanitize_schema_text(text) ⇒ String?
Prepare description text for embedding in a JSON-LD
<script>tag.
Instance Method Summary collapse
-
#get(options = {}) ⇒ Hash
Get rendered product HTML.
-
#render_for_locale(sku, locale = 'en-US', include_schema: true) ⇒ String?
Render product embed HTML for the frontend (blog display) This is called during content refresh and normal rendering Handles locale-aware pricing and availability checks.
Class Method Details
.curl_typographic_quotes(text) ⇒ String
Convert straight ASCII quotes to curly typographic quotes per the
project's curly-quote convention
(https://typographyforlawyers.com/straight-and-curly-quotes.html).
Kept as a thin shim around Heatwave::TypographicQuotes.curl_plain
so existing call sites continue to work; new callers should use
the module method directly.
320 321 322 |
# File 'app/services/oembed/product_provider.rb', line 320 def self.curl_typographic_quotes(text) Heatwave::TypographicQuotes.curl_plain(text) end |
.sanitize_schema_text(text) ⇒ String?
Prepare description text for embedding in a JSON-LD <script> tag.
Two concerns:
- Word boundaries — replace block-level tags with spaces before
stripping so<p>foo</p><p>bar</p>becomesfoo bar, not
foobar. - Quote safety — convert straight ASCII quotes to curly typographic
quotes via Heatwave::TypographicQuotes.curl_plain. Even with
to_jsonescaping straight"as\", any tool that round-trips
the JSON-LD as HTML text (Redactor, Nokogiri-based refreshers, etc.)
can unescape\"back to", leaving invalid JSON inside the
script tag. Curly quotes are different code points entirely and
survive every round-trip intact.
Idempotent: re-running on already-sanitized text yields the same
output (curly quotes pass through, block tags are already gone).
299 300 301 302 303 304 305 306 |
# File 'app/services/oembed/product_provider.rb', line 299 def self.sanitize_schema_text(text) return text if text.blank? spaced = text.to_s.gsub(BLOCK_TAG_REGEX, ' ') sanitized = ActionView::Base.full_sanitizer.sanitize(spaced) decoded = CGI.unescapeHTML(sanitized).squish Heatwave::TypographicQuotes.curl_plain(decoded) end |
Instance Method Details
#get(options = {}) ⇒ Hash
Get rendered product HTML
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'app/services/oembed/product_provider.rb', line 40 def get( = {}) sku = [:sku].to_s.strip locale = [:locale].to_s.presence || 'en-US' = [:embedded_asset_uuid].presence raise ProductNotFoundError, 'No SKU provided' if sku.blank? # Try exact match first, then case-insensitive item = Item.find_by(sku: sku) || Item.where('UPPER(sku) = ?', sku.upcase).first raise ProductNotFoundError, "Product not found: #{sku}" if item.nil? # For CRM editor preview, show the product with locale-aware pricing # The frontend rendering will handle final availability checks build_response(item, sku, locale, embedded_asset_uuid: ) end |
#render_for_locale(sku, locale = 'en-US', include_schema: true) ⇒ String?
Render product embed HTML for the frontend (blog display)
This is called during content refresh and normal rendering
Handles locale-aware pricing and availability checks
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'app/services/oembed/product_provider.rb', line 64 def render_for_locale(sku, locale = 'en-US', include_schema: true) sku_stripped = sku.to_s.strip item = Item.find_by(sku: sku_stripped) || Item.where('UPPER(sku) = ?', sku_stripped.upcase).first return nil if item.nil? catalog_id = catalog_id_for_locale(locale) catalog_item = item.catalog_items.find_by(catalog_id: catalog_id) # Check availability - return nil if product shouldn't be displayed return nil unless product_available?(item, catalog_item) # Render the product card card_html = render_product_card(item, catalog_item, locale) return nil if card_html.nil? # Optionally include JSON-LD schema for SEO if include_schema schema_html = render_product_schema(item, catalog_item, locale) "#{card_html}#{schema_html}" else card_html end end |