Class: Amazon::BrowseTreeGuideRow

Inherits:
Object
  • Object
show all
Defined in:
app/services/amazon/browse_tree_guide_row.rb

Overview

One row of an Amazon Browse Tree Guide, normalized.

The BTGs (Seller Central /help/hub/reference/1641) are the only full-tree
source for browse nodes — SP-API has no endpoint that dumps them. Three
columns matter: node id, node path, and Amazon's "Terms to Use", which
states what a listing must carry to be filed under that node.

Parsing lives here rather than in the import task so it can be tested: the
keyword it extracts is submitted verbatim to Amazon as item_type_keyword,
and a wrong value silently mis-files a product.

Constant Summary collapse

KEYWORD =

Amazon writes the terms in three shapes:

item_type_keyword:wall-light-switches
item_type_keyword:baby-keepsake-products AND specific_uses_keywords:christening
item_type_keyword:bed-skirts OR item_type_keyword:bed-valances

Only the first item_type_keyword is taken. The AND form names a SECOND
attribute we are not importing, so keeping the tail would store
"baby-keepsake-products AND specific_uses_keywords:christening" as the
keyword — a value Amazon does not accept. The OR form lists alternatives,
any one of which qualifies, so the first is as good as the rest.

/item_type_keyword\s*:\s*([a-z0-9][a-z0-9-]*)/i
TRAILING_FRACTION =

roo hands back numeric cells as Float ("16351481.0"), so strip a trailing
decimal fraction BEFORE removing separators — a bare gsub(/\D/) would turn
"16351481.0" into "163514810".

/\.\d+\z/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(row) ⇒ BrowseTreeGuideRow

Prefer build, which returns nil for a row that names no node.

Parameters:

  • row (Array)

    cells A, B, C of one guide row



45
46
47
48
49
# File 'app/services/amazon/browse_tree_guide_row.rb', line 45

def initialize(row)
  @node_id   = row[0].to_s.sub(TRAILING_FRACTION, '').gsub(/\D/, '').presence
  @node_path = row[1].to_s.strip
  @keyword   = row[2].to_s[KEYWORD, 1]
end

Instance Attribute Details

#keywordObject (readonly)

Returns the value of attribute keyword.



35
36
37
# File 'app/services/amazon/browse_tree_guide_row.rb', line 35

def keyword
  @keyword
end

#node_idObject (readonly)

Returns the value of attribute node_id.



35
36
37
# File 'app/services/amazon/browse_tree_guide_row.rb', line 35

def node_id
  @node_id
end

#node_pathObject (readonly)

Returns the value of attribute node_path.



35
36
37
# File 'app/services/amazon/browse_tree_guide_row.rb', line 35

def node_path
  @node_path
end

Class Method Details

.build(row) ⇒ BrowseTreeGuideRow?

Returns nil when the row carries no usable node.

Parameters:

  • row (Array)

    cells A, B, C of one guide row

Returns:



39
40
41
# File 'app/services/amazon/browse_tree_guide_row.rb', line 39

def self.build(row)
  new(row).then { |parsed| parsed.usable? ? parsed : nil }
end

Instance Method Details

#display_only?Boolean

A node Amazon lists for display only: it publishes no terms, and its own
instructions say such nodes "aren't used themselves". Nothing we submit
can place a product there, so assigning one to a catalog item guarantees a
permanent category mismatch.

Returns:

  • (Boolean)


60
# File 'app/services/amazon/browse_tree_guide_row.rb', line 60

def display_only? = keyword.nil?

#to_hHash

The shape the import task feeds to AmazonBrowseNode.insert_all.

Returns:

  • (Hash)


64
# File 'app/services/amazon/browse_tree_guide_row.rb', line 64

def to_h = { node_id:, node_path:, keyword: }

#usable?Boolean

Whether the row identifies a node at all. Guides carry section headers and
spacer rows that parse to blanks.

Returns:

  • (Boolean)


54
# File 'app/services/amazon/browse_tree_guide_row.rb', line 54

def usable? = node_id.present? && node_path.present?