Class: Feed::Google::ListGenerator
- Inherits:
-
BaseService
- Object
- BaseService
- Feed::Google::ListGenerator
- Defined in:
- app/services/feed/google/list_generator.rb
Overview
Pre-generates the google merchant product feed and store it in the database for fast retrieval
Instance Method Summary collapse
-
#append_xml_catalog_item(xml, cip) ⇒ Object
See https://support.google.com/merchants/answer/7052112?visit_id=638048221805784930-2204873326&rd=1 for all possible attributes.
- #load_products(catalog, limit: nil, catalog_item_ids: nil) ⇒ Object
-
#process(catalogs: nil, catalog_item_ids: nil, limit: nil, delete_all: nil) ⇒ Object
Main method.
Instance Method Details
#append_xml_catalog_item(xml, cip) ⇒ Object
See https://support.google.com/merchants/answer/7052112?visit_id=638048221805784930-2204873326&rd=1
for all possible attributes
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'app/services/feed/google/list_generator.rb', line 78 def append_xml_catalog_item(xml, cip) xml.entry do xml.send :'g:id', cip.id xml.send :'g:title', cip.reported_name_for_google xml.send :'g:description', cip.description xml.send :'g:link', cip.url xml.send :'g:image_link', cip.image_link xml.send :'g:condition', cip.condition cip.additional_image_links.each { |link| xml.send :'g:additional_image_link', link } xml.send :'g:google_product_category', cip.google_product_category xml.send :'g:product_type', cip.product_type xml.send :'g:availability', cip.availability xml.send :'g:price', cip.price_with_currency xml.send :'g:suggested_retail_price', cip.price_with_currency xml.send(:'g:gtin', cip.upc) if cip.upc.present? xml.send :'g:mpn', cip.mpn xml.send :'g:brand', cip.brand # https://support.google.com/merchants/answer/6231538?hl=en # https://support.google.com/merchants/answer/9450803?hl=en#zippy=%2Cstep-add-variant-attributes if cip.has_variants? && (cip.color_info.present? || cip.size_info.present?) xml.send(:'g:size', cip.size_info) if cip.size_info.present? xml.send(:'g:color', cip.color_info) if cip.color_info.present? xml.send :'g:item_group_id', cip.item_group_name end xml.send :'g:shipping_weight', cip.shipping_weight xml.send :'g:shipping_width', cip.shipping_width xml.send :'g:shipping_length', cip.shipping_length xml.send :'g:shipping_height', cip.shipping_height xml.send :'g:max_handling_time', 1 if cip.sale_price_in_effect? xml.send :'g:sale_price', cip.sale_price_with_currency xml.send :'g:sale_price_effective_date', cip.sale_price_date_range if cip.sale_price_date_range.present? end xml.send :'g:ships_from_country', cip.ships_from_country_iso xml.send :'g:pickup_method', cip.pickup_method xml.send :'g:pickup_sla', cip.pickup_sla xml.send :'g:link_template', "#{cip.url}?g_store_code={store_code}" end end |
#load_products(catalog, limit: nil, catalog_item_ids: nil) ⇒ Object
68 69 70 71 72 73 74 |
# File 'app/services/feed/google/list_generator.rb', line 68 def load_products(catalog, limit: nil, catalog_item_ids: nil) products = catalog.view_product_catalogs.includes(:catalog_item, :item).joins(:catalog_item).merge(CatalogItem.for_google_feed) products = products.limit(limit) if limit.present? products = products.where(catalog_item_id: catalog_item_ids) if catalog_item_ids.present? products = products.map { |ci| Feed::Google::GoogleProductPresenter.new(ci) } products.select(&:valid_for_google?) end |
#process(catalogs: nil, catalog_item_ids: nil, limit: nil, delete_all: nil) ⇒ Object
Main method.
- catalogs: specify catalogs otherwise will be main catalogs (US and CA)
- catalog_item_ids: filter by specific catalog_item_ids, e.g you want to update only one product
- limit: optional limit to number of records to process
- delete_all: truncate all google feed records in the catalog, useful for periodic cleanups
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/services/feed/google/list_generator.rb', line 8 def process(catalogs: nil, catalog_item_ids: nil, limit: nil, delete_all: nil) require 'activerecord-import/base' require 'activerecord-import/active_record/adapters/postgresql_adapter' res = { products: 0 } catalogs ||= Catalog.for_google_feed if delete_all.nil? if catalog_item_ids.present? delete_all = false elsif catalogs.present? delete_all = true end end # If catalog_item_ids are specified, we need to delete them first regardless if catalog_item_ids.present? GoogleFeed.where(catalog_item_id: catalog_item_ids).delete_all # If catalog item ids are specified, we only need catalogs which includes these catalogs = catalogs.joins(:catalog_items).where(catalog_items: { id: catalog_item_ids }) end catalogs.each do |catalog| I18n.with_locale catalog.locale_for_catalog do logger.info "Processing GoogleFeed items for catalog #{catalog.id}" products = load_products(catalog, limit: limit, catalog_item_ids: catalog_item_ids) inserts = [] products.each do |p| logger.info "Generating xml data for product #{p.id} mpn:#{p.mpn} upc:#{p.upc}" builder = Nokogiri::XML::Builder.new do |xml| append_xml_catalog_item(xml, p) end xml_data = builder.to_xml save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION catalog = p.catalog_item.catalog res[:products] += 1 inserts << { catalog_id: catalog.id, catalog_item_id: p.catalog_item_id, sku: p.item_sku, target_country_iso: catalog.country&.iso, locale: catalog.locale_for_catalog, xml_data: xml_data } end GoogleFeed.transaction do if delete_all logger.info 'Purging GoogleFeed' GoogleFeed.where(catalog_id: catalog.id).delete_all end logger.info "Importing #{inserts.size} GoogleFeedRecords" GoogleFeed.import inserts, on_duplicate_key_update: { conflict_target: [:catalog_item_id], columns: %i[xml_data sku target_country_iso locale] } end end end res end |