Class: Showroom::Product
- Extended by:
- Core::Countable
- Defined in:
- lib/showroom/models/product.rb
Overview
Represents a Shopify product with associations, convenience methods, and class-level query methods that delegate to client.
Constant Summary
Constants included from Core::Countable
Core::Countable::MAX_COUNT, Core::Countable::MAX_PAGE, Core::Countable::MAX_PER_PAGE
Instance Attribute Summary
Attributes inherited from Resource
Class Method Summary collapse
-
.all(max_pages: nil, force_all_without_limit: false, **params) ⇒ Enumerator<Product>
Returns an Enumerator that iterates over products across multiple pages.
-
.each_page(max_pages: nil, force_all_without_limit: false, limit: Showroom.per_page, **params) {|products, page| ... } ⇒ void
Iterates through pages of products, yielding each page.
-
.find(handle) ⇒ Product
Fetches a single product by handle.
- .index_key ⇒ Object
- .index_path ⇒ Object
-
.where(limit: Showroom.per_page, **params) ⇒ Array<Product>
Fetches products matching the given query parameters.
Instance Method Summary collapse
-
#available? ⇒ Boolean
Returns true when at least one variant is available for purchase.
-
#featured_image ⇒ ProductImage?
Returns the first image, or nil if there are no images.
-
#main_image ⇒ ProductImage?
Returns the image whose
positionfield equals 1, or nil if none match. -
#price ⇒ String?
Returns the lowest variant price as a String.
-
#price_range ⇒ String?
Returns a price range string (“min–max”) or just the price if all variants share the same price.
-
#prices ⇒ Array<String>
Returns unique prices across all variants as an Array of Strings.
-
#url ⇒ String
Returns the canonical storefront URL for this product.
Methods included from Core::Countable
Methods inherited from Resource
#==, #[], has_many, has_one, #initialize, #inspect, main_attr_keys, main_attrs, #method_missing, #respond_to_missing?, #to_h
Constructor Details
This class inherits a constructor from Showroom::Resource
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Showroom::Resource
Class Method Details
.all(max_pages: nil, force_all_without_limit: false, **params) ⇒ Enumerator<Product>
Returns an Enumerator that iterates over products across multiple pages.
You must pass either max_pages: (an explicit ceiling) or set force_all_without_limit: true to acknowledge that the number of requests is unbounded. The latter emits a warning.
58 59 60 61 62 63 64 65 |
# File 'lib/showroom/models/product.rb', line 58 def all(max_pages: nil, force_all_without_limit: false, **params) Enumerator.new do |yielder| each_page(max_pages: max_pages, force_all_without_limit: force_all_without_limit, **params) do |page_products, _page| page_products.each { |p| yielder << p } end end end |
.each_page(max_pages: nil, force_all_without_limit: false, limit: Showroom.per_page, **params) {|products, page| ... } ⇒ void
This method returns an undefined value.
Iterates through pages of products, yielding each page.
You must pass either max_pages: or force_all_without_limit: true. Without an explicit ceiling, unbounded pagination can issue dozens of HTTP requests silently. When force_all_without_limit: true is given, a warning is emitted and iteration proceeds up to pagination_depth.
85 86 87 88 89 90 91 92 |
# File 'lib/showroom/models/product.rb', line 85 def each_page(max_pages: nil, force_all_without_limit: false, limit: Showroom.per_page, **params, &blk) validate_pagination_args!(max_pages, force_all_without_limit) effective_depth = max_pages || Showroom.client.pagination_depth Showroom.client.paginate('/products.json', 'products', params.merge(limit: limit), max_pages: effective_depth) do |items, page| blk.call(items.map { |h| new(h) }, page) end end |
.find(handle) ⇒ Product
Fetches a single product by handle.
39 40 41 42 43 |
# File 'lib/showroom/models/product.rb', line 39 def find(handle) Showroom.client.get("/products/#{handle}.json") .fetch('product') { raise Showroom::NotFound, handle } .then { |h| new(h) } end |
.index_key ⇒ Object
21 |
# File 'lib/showroom/models/product.rb', line 21 def index_key = 'products' |
.index_path ⇒ Object
20 |
# File 'lib/showroom/models/product.rb', line 20 def index_path = '/products.json' |
.where(limit: Showroom.per_page, **params) ⇒ Array<Product>
Fetches products matching the given query parameters.
28 29 30 31 32 |
# File 'lib/showroom/models/product.rb', line 28 def where(limit: Showroom.per_page, **params) Showroom.client.get('/products.json', params.merge(limit: limit)) .fetch('products', []) .map { |h| new(h) } end |
Instance Method Details
#available? ⇒ Boolean
Returns true when at least one variant is available for purchase.
131 132 133 |
# File 'lib/showroom/models/product.rb', line 131 def available? variants.any?(&:available?) end |
#featured_image ⇒ ProductImage?
Returns the first image, or nil if there are no images.
138 139 140 |
# File 'lib/showroom/models/product.rb', line 138 def featured_image images.first end |
#main_image ⇒ ProductImage?
Returns the image whose position field equals 1, or nil if none match.
Unlike #featured_image (which returns images.first regardless of position), this explicitly matches on the position attribute.
168 169 170 171 172 |
# File 'lib/showroom/models/product.rb', line 168 def main_image images.find do |img| img['position'] == 1 end end |
#price ⇒ String?
Returns the lowest variant price as a String.
113 114 115 |
# File 'lib/showroom/models/product.rb', line 113 def price variants.min_by { |v| v['price'].to_f }&.then { |v| v['price'] } end |
#price_range ⇒ String?
Returns a price range string (“min–max”) or just the price if all variants share the same price.
121 122 123 124 125 126 |
# File 'lib/showroom/models/product.rb', line 121 def price_range prices = variants.map { |v| v['price'] }.uniq return nil if prices.empty? prices.length == 1 ? prices.first : "#{prices.min} - #{prices.max}" end |
#prices ⇒ Array<String>
Returns unique prices across all variants as an Array of Strings.
Unlike #price (lowest single price) or #price_range (formatted string), this returns the raw deduplicated list useful for custom rendering.
156 157 158 159 160 |
# File 'lib/showroom/models/product.rb', line 156 def prices variants.map do |variant| variant['price'] end.uniq end |