Class: Item::ImageRetriever
- Inherits:
-
BaseService
- Object
- BaseService
- Item::ImageRetriever
- Defined in:
- app/services/item/image_retriever.rb
Overview
Retrieves all the images associated with a particular item. Queries main image, product line main image,
image library for image tagged directly to the item or to the product line and its ancestor
Defined Under Namespace
Classes: Result
Instance Attribute Summary
Attributes inherited from BaseService
Instance Method Summary collapse
- #ignore_individual_query_limits? ⇒ Boolean
-
#initialize(options = {}) ⇒ ImageRetriever
constructor
==== Initialization options (pass as a hash).
- #item_images_query(item, limit: nil) ⇒ Object
- #item_images_query_limit ⇒ Object
- #item_primary_image(item) ⇒ Object
- #item_primary_product_line_image(item) ⇒ Object
-
#library_product_line_images(item) ⇒ Object
Ordered product-line / category images (same rules as internal +product_line_query+).
-
#max_images ⇒ Object
Setting a maximum of 100 by default.
-
#process(item) ⇒ Object
Retrieves all product specifications available to a given item.
- #product_line_query(item) ⇒ Object
- #product_line_query_limit ⇒ Object
Methods inherited from BaseService
#log_debug, #log_error, #log_info, #log_warning, #logger, #tagged_logger
Constructor Details
#initialize(options = {}) ⇒ ImageRetriever
==== Initialization options (pass as a hash)
- +:tags+ - filter all image library images retrieval by these tags, specify one or many to query on the presence of any of these tags
- +:locales+ - filter all images by those having any of these locales specifically or no locales at all
- +:item_images_query_limit+ - how many images max to retrieve from the item library, default to 10
- +:product_line_query_limit+ - how many images max to retrieve from the item library linked to the product line or its ancestor, default is 5
- +:vignette_installation_images_query_limit+ - how many vignette room image to retrieve, default to 3
- +:max_images+ - At max, return only this number of images
- +:ignore_individual_query_limits+ true/false, default: false, if true then all default limits are ignored
- +:ignore_item_primary_image+ - true/false
- +:ignore_product_line_primary_image+ - true/false
- +:ignore_vignette_installation_image+ - true/false
- +:ignore_kit_components+ - true/false, do not process kit components for image retrieval
- +:ignore_image_ids+ - array of image ids to ignore, useful if you build compound queries
- +:min_width+ - The minimum image width
- +:min_height+ - The minimum image height
- +:include_secondary_product_lines+ - true/false, include images from the item's secondary product lines (and their ancestors)
- +:exclude_tags+ - array of tags to exclude from all queries (e.g., DigitalAsset::HIDDEN_TAGS)
==== Examples
ir = Item::ImageRetriever.new(tags: 'for-product-page', item_images_query_limit: 20)
52 53 54 |
# File 'app/services/item/image_retriever.rb', line 52 def initialize( = {}) super(.compact) end |
Instance Method Details
#ignore_individual_query_limits? ⇒ Boolean
112 113 114 |
# File 'app/services/item/image_retriever.rb', line 112 def ignore_individual_query_limits? [:ignore_individual_query_limits].present? end |
#item_images_query(item, limit: nil) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'app/services/item/image_retriever.rb', line 128 def item_images_query(item, limit: nil) return [] if [:item_images_query_limit]&.zero? item_images = Image.active.by_item_ids(item.id).order(:position) item_images = item_images.where.not(id: [:ignore_image_ids]) if [:ignore_image_ids].present? item_images = item_images.tagged_with([:tags]) if [:tags].present? item_images = item_images.tagged_with_all([:tags_all]) if [:tags_all].present? item_images = item_images.not_tagged_with([:exclude_tags]) if [:exclude_tags].present? item_images = item_images.localized_for_or_not([:locales]) if [:locales].present? item_images = item_images.limit(item_images_query_limit) if item_images_query_limit item_images = item_images.where(Image[:attachment_width].gteq([:min_width])) if [:min_width].present? item_images = item_images.where(Image[:attachment_height].gteq([:min_height])) if [:min_height].present? item_images = item_images.limit(limit) if limit.present? item_images.to_a end |
#item_images_query_limit ⇒ Object
144 145 146 147 148 |
# File 'app/services/item/image_retriever.rb', line 144 def item_images_query_limit return if ignore_individual_query_limits? [:item_images_query_limit] || 25 end |
#item_primary_image(item) ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'app/services/item/image_retriever.rb', line 96 def item_primary_image(item) return if [:ignore_item_primary_image].present? ipi = item.primary_image || item.new_item&.primary_image return unless ipi # If explicitly requested, apply tag filter to the primary image if [:tags].present? && [:respect_primary_image_tags].to_b = (ipi. || []).map(&:to_s) = [[:tags]].flatten.compact.map(&:to_s) return unless .intersect?() end ipi end |
#item_primary_product_line_image(item) ⇒ Object
116 117 118 119 120 121 122 123 124 125 126 |
# File 'app/services/item/image_retriever.rb', line 116 def item_primary_product_line_image(item) return if [:ignore_product_line_primary_image].present? return unless (ippli = item.primary_product_line.try(:primary_image_inherited)) # If we specified tags to filter on, we only pull if the primary image has this tag too # return unless !options[:strict_tags].to_b && options[:tags].nil? || (options[:tags].present? && ((ippli.tags || []) & options[:tags]).present?) # If the image has an applicable product category and it is not part of the item's product category id we discard return if (ippc_ids = ippli.all_my_applicable_product_categories.filter_map(&:id).uniq).present? && ippc_ids.exclude?(item.product_category_id) ippli end |
#library_product_line_images(item) ⇒ Object
Ordered product-line / category images (same rules as internal +product_line_query+).
Used by CRM image management to rank library results after item-specific and sibling tiers.
152 153 154 |
# File 'app/services/item/image_retriever.rb', line 152 def library_product_line_images(item) product_line_query(item) end |
#max_images ⇒ Object
Setting a maximum of 100 by default
92 93 94 |
# File 'app/services/item/image_retriever.rb', line 92 def max_images [:max_images] || 100 end |
#process(item) ⇒ Object
Retrieves all product specifications available to a given item
==== Parameters
- +item+ - The item for which you want to retrieve images
==== Returns
A Result object with
- +all_images+ - an array of images combined
- +images_grouped+ - hash wrapping all images as a single group (origin grouping removed)
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'app/services/item/image_retriever.rb', line 67 def process(item) item_to_use = item.new_item || item all_images = [] all_images += [item_primary_image(item_to_use)].compact # all_images += [item_primary_product_line_image(item_to_use)].compact unless all_images.size >= max_images all_images += item_images_query(item_to_use) unless all_images.size >= max_images all_images += product_line_query(item_to_use) unless all_images.size >= max_images if ![:ignore_kit_components].to_b && (kit_items = item_to_use.get_kit_items(spec_only: true)).present? kit_items.each do |kit_item| next if all_images.size >= max_images = .dup [:item_images_query_limit] = 1 [:max_images] = 1 [:ignore_kit_components] = true kit_ir = Item::ImageRetriever.new(**) all_images += kit_ir.process(kit_item).all_images end end all_images = all_images.compact.uniq all_images = all_images[0..(max_images - 1)] Result.new(all_images:, images_grouped: { nil => all_images }) end |
#product_line_query(item) ⇒ Object
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'app/services/item/image_retriever.rb', line 156 def product_line_query(item) return [] unless item.primary_product_line return [] if [:product_line_query_limit]&.zero? primary_pl_ids = item.primary_product_line.self_and_ancestors_ids secondary_pl_ids = if [:include_secondary_product_lines] item.product_lines.where.not(id: item.primary_product_line_id).flat_map(&:self_and_ancestors_ids) else [] end pl_ids = (primary_pl_ids + secondary_pl_ids).uniq pc_ids = item.product_category.self_and_ancestors_ids item_images = Image.active.includes(:product_lines, :product_categories).order(:position) item_images = item_images.by_product_line_id_direct(pl_ids) item_images = item_images.by_product_category_id_direct_or_optional(pc_ids) item_images = item_images.tagged_with([:tags]) if [:tags].present? item_images = item_images.tagged_with_all([:tags_all]) if [:tags_all].present? item_images = item_images.not_tagged_with([:exclude_tags]) if [:exclude_tags].present? item_images = item_images.limit(product_line_query_limit) if product_line_query_limit item_images = item_images.where(Image[:attachment_width].gteq([:min_width])) if [:min_width].present? item_images = item_images.where(Image[:attachment_height].gteq([:min_height])) if [:min_height].present? # We have to eliminate images which are irrelvant to our applicable product category item_images = item_images.select do |ii| ippc_ids = ii.all_my_applicable_product_categories.filter_map(&:id).uniq # Either the image has no product category applicable in which case it is included, otherwise the item product category has to be part of it ippc_ids.blank? || ippc_ids.include?(item.product_category_id) end # Prioritize images closest to the item's product line and product category primary_pl_id = item.primary_product_line_id primary_ancestor_ids = item.primary_product_line.ancestors.map(&:id) direct_secondary_ids = item.product_lines.where.not(id: primary_pl_id).ids secondary_ancestor_ids = (secondary_pl_ids - direct_secondary_ids) item_pc_id = item.product_category_id item_images.sort_by do |ii| img_pl_ids = ii.product_lines.map(&:id) img_pc_ids = ii.product_categories.map(&:id) pl_specificity = if img_pl_ids.include?(primary_pl_id) 0 elsif img_pl_ids.intersect?(direct_secondary_ids) 1 elsif img_pl_ids.intersect?(primary_ancestor_ids) 2 elsif img_pl_ids.intersect?(secondary_ancestor_ids) 3 else 4 end pc_specificity = img_pc_ids.include?(item_pc_id) ? 0 : 1 [pl_specificity, pc_specificity, ii.position.to_i] end end |
#product_line_query_limit ⇒ Object
215 216 217 218 219 |
# File 'app/services/item/image_retriever.rb', line 215 def product_line_query_limit return if ignore_individual_query_limits? [:product_line_query_limit] || 10 end |