Class: Spree::OrderRouting::Strategy::Reducer
- Inherits:
-
Object
- Object
- Spree::OrderRouting::Strategy::Reducer
- Defined in:
- app/models/spree/order_routing/strategy/reducer.rb
Overview
Walks rules in priority order and applies a “first non-tie wins” reducer.
For each rule:
1. Drop rankings where rank is nil (rule abstains for that location).
2. Find the location(s) with the lowest rank (best).
3. Unique winner -> return it.
4. Tie -> carry the tied set forward to the next rule.
Out of rules with ties: prefer the StockLocation marked default, then by id. Guarantees a winner whenever locations is non-empty.
Instance Method Summary collapse
-
#initialize(rules, order:) ⇒ Reducer
constructor
A new instance of Reducer.
- #pick(locations) ⇒ Spree::StockLocation?
-
#rank_all(locations) ⇒ Array<Spree::StockLocation>
Returns every input location, ordered best-first by the same rule chain that drives #pick.
Constructor Details
#initialize(rules, order:) ⇒ Reducer
Returns a new instance of Reducer.
17 18 19 20 |
# File 'app/models/spree/order_routing/strategy/reducer.rb', line 17 def initialize(rules, order:) @rules = rules @order = order end |
Instance Method Details
#pick(locations) ⇒ Spree::StockLocation?
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'app/models/spree/order_routing/strategy/reducer.rb', line 24 def pick(locations) return nil if locations.empty? remaining = locations remaining_ids = remaining.map(&:id).to_set @rules.each do |rule| rankings = rule.rank(@order, remaining).select do |r| r.rank && remaining_ids.include?(r.location.id) end next if rankings.empty? min_rank = rankings.map(&:rank).min top = rankings.select { |r| r.rank == min_rank }.map(&:location) return top.first if top.size == 1 remaining = top remaining_ids = top.map(&:id).to_set end remaining.min_by { |l| [l.default? ? 0 : 1, l.id] } end |
#rank_all(locations) ⇒ Array<Spree::StockLocation>
Returns every input location, ordered best-first by the same rule chain that drives #pick. Each successive location is the best of what remains — used by Strategy::Rules to fan out an allocation across multiple locations when no single location covers the cart.
55 56 57 58 59 60 61 62 63 64 |
# File 'app/models/spree/order_routing/strategy/reducer.rb', line 55 def rank_all(locations) remaining = locations.dup ordered = [] until remaining.empty? chosen = pick(remaining) or break ordered << chosen remaining = remaining.reject { |l| l.id == chosen.id } end ordered end |