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 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, #options, #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)
31 32 33 |
# File 'app/services/item/image_retriever.rb', line 31 def initialize( = {}) super(.compact) end |
Instance Method Details
#ignore_individual_query_limits? ⇒ Boolean
91 92 93 |
# File 'app/services/item/image_retriever.rb', line 91 def ignore_individual_query_limits? [:ignore_individual_query_limits].present? end |
#item_images_query(item, limit: nil) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'app/services/item/image_retriever.rb', line 107 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
123 124 125 126 127 |
# File 'app/services/item/image_retriever.rb', line 123 def item_images_query_limit return if ignore_individual_query_limits? [:item_images_query_limit] || 25 end |
#item_primary_image(item) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'app/services/item/image_retriever.rb', line 75 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 ( & ).present? end ipi end |
#item_primary_product_line_image(item) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 |
# File 'app/services/item/image_retriever.rb', line 95 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.map(&:id).compact.uniq).present? && !ippc_ids.include?(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.
131 132 133 |
# File 'app/services/item/image_retriever.rb', line 131 def library_product_line_images(item) product_line_query(item) end |
#max_images ⇒ Object
Setting a maximum of 100 by default
71 72 73 |
# File 'app/services/item/image_retriever.rb', line 71 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)
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'app/services/item/image_retriever.rb', line 46 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
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 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 |
# File 'app/services/item/image_retriever.rb', line 135 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.map(&:id).compact.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).pluck(:id) secondary_ancestor_ids = (secondary_pl_ids - direct_secondary_ids) item_pc_id = item.product_category_id item_images = 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 & direct_secondary_ids).present? 1 elsif (img_pl_ids & primary_ancestor_ids).present? 2 elsif (img_pl_ids & secondary_ancestor_ids).present? 3 else 4 end pc_specificity = img_pc_ids.include?(item_pc_id) ? 0 : 1 [pl_specificity, pc_specificity, ii.position.to_i] end item_images end |
#product_line_query_limit ⇒ Object
196 197 198 199 200 |
# File 'app/services/item/image_retriever.rb', line 196 def product_line_query_limit return if ignore_individual_query_limits? [:product_line_query_limit] || 10 end |