Class: Spree::Channel
- Inherits:
-
Object
- Object
- Spree::Channel
- Defined in:
- app/models/spree/channel.rb,
app/models/spree/channel/gating.rb
Overview
Lightweight distribution surface within a Store: online storefront, POS, marketplace integration, wholesale portal. Channels carry order attribution and the routing-strategy override.
Defined Under Namespace
Modules: Gating
Constant Summary collapse
- DEFAULT_CODE =
'online'.freeze
Constants included from Gating
Instance Method Summary collapse
-
#add_products(product_ids, published_at: nil, unpublished_at: nil) ⇒ Integer
Publishes the given products on this channel by creating/upserting ProductPublications.
- #can_be_deleted? ⇒ Boolean
-
#remove_products(product_ids) ⇒ Integer
Unpublishes the given products from this channel.
Methods included from Gating
#resolved_guest_checkout, #resolved_storefront_access, #storefront_login_required?, #storefront_prices_hidden?
Methods included from Metadata
#metadata, #metadata=, #public_metadata=
Instance Method Details
#add_products(product_ids, published_at: nil, unpublished_at: nil) ⇒ Integer
Publishes the given products on this channel by creating/upserting ProductPublications. Optionally sets the publication window; if not given, the products will be published immediately with no end date.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'app/models/spree/channel.rb', line 57 def add_products(product_ids, published_at: nil, unpublished_at: nil) product_ids = Array(product_ids).map(&:to_s).uniq return 0 if product_ids.empty? now = Time.current # Only include window columns in the upsert payload when the caller # explicitly passed a value. Leaving them out keeps existing # publication schedules intact on re-publish — otherwise +on_duplicate: # :update+ + +update_only+ would rewrite scheduled +published_at+ / # +unpublished_at+ to NULL whenever the bulk action re-runs without # dates. base = { channel_id: id, created_at: now, updated_at: now } base[:published_at] = published_at unless published_at.nil? base[:unpublished_at] = unpublished_at unless unpublished_at.nil? records_to_upsert = product_ids.map { |product_id| base.merge(product_id: product_id) } # Only update the window columns the caller passed. When neither was # passed, treat re-publish as a no-op (+on_duplicate: :skip+ → MySQL # +INSERT IGNORE+, PG/SQLite +ON CONFLICT DO NOTHING+). update_columns = [] update_columns << :published_at unless published_at.nil? update_columns << :unpublished_at unless unpublished_at.nil? opts = if update_columns.empty? { on_duplicate: :skip } else { record_timestamps: false, update_only: update_columns, on_duplicate: :update } end # MySQL infers the conflict target from the table's unique constraints # and rejects an explicit +unique_by+; PostgreSQL/SQLite require it. opts[:unique_by] = %i[product_id channel_id] unless mysql_adapter? Spree::ProductPublication.upsert_all(records_to_upsert, **opts) products = Spree::Product.where(id: product_ids) products.touch_all products.each(&:enqueue_search_index) touch records_to_upsert.size end |
#can_be_deleted? ⇒ Boolean
117 118 119 |
# File 'app/models/spree/channel.rb', line 117 def can_be_deleted? !default? end |
#remove_products(product_ids) ⇒ Integer
Unpublishes the given products from this channel.
102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'app/models/spree/channel.rb', line 102 def remove_products(product_ids) product_ids = Array(product_ids).map(&:to_s).uniq return 0 if product_ids.empty? count = publications.where(product_id: product_ids).destroy_all.size products = Spree::Product.where(id: product_ids) products.touch_all products.each(&:enqueue_search_index) touch if count.positive? count end |