A for loop runs a block of code once for each item in a collection. It’s how you do something to every line item, every shipment line, every comment, etc.
for order_lines in order
set order_line.custom.note to "Processed"
end
For each line item on the order, this sets that line’s note field. The loop variable inside the block is the singular form (order_line) of the collection name (order_lines).
If you’ve used a spreadsheet: A
forloop is like applying a formula to every row in a column. The collection is the column; the body is the formula.
The shape
for collection in model
body
end
| Part | Example | Meaning |
|---|---|---|
collection |
order_lines |
The name of the collection on the model. |
model |
order |
The model that owns the collection. |
body |
set order_line.custom.note to "..." |
What to do with each item. Inside, refer to the current item by its singular name (order_line). |
Conditional actions in a loop
Combine with when to act only on some items:
for order_lines in order
when order_line.sku starts_with "HAZMAT-" then
set order_line.custom.requires_signature to true
end
end
For every line item, if its SKU starts with “HAZMAT-“, flag it.
Nested loops
Loops nest naturally. A common pattern: iterate line items, then iterate something inside each line.
for order_lines in order
for inventories in order_line
when inventory.available > 0 then
route order_line to warehouse inventory.warehouse_id
end
end
end
The inner loop iterates each order_line’s inventories collection. Variables inside refer to whatever loop they’re in — order_line for the outer, inventory for the inner.
Iterating regex matches in text
There’s a second form of for that iterates over the parts of a string that match a regex:
for /(?<num>\d+)/ in order.notes
print "Found number: " & num
end
For every group of digits found in order.notes, the named capture (num) is bound, and the body runs once with that capture available.
This is the only way to “split” a string in BGL — there’s no split function.
What’s available inside a loop
-
The loop variable —
order_line,inventory, etc. -
The outer model —
orderis still accessible insidefor order_lines in order. - Session variables — see Variables.
What’s not available
BGL doesn’t support:
-
breakorcontinue— you can’t exit a loop early or skip iterations. To approximate “stop after first match”, use a session variable as a flag:set $found to false for order_lines in order when not $found and order_line.sku is "TARGET" then set $found to true # do the work end end -
An index variable — there’s no built-in way to know “I’m on the third item”. Use indexed access (
order_lines[2].sku) when you need a specific position. See Collections and Source Data. -
take(n)— you can’t limit a loop to the first N items. The full collection always iterates.
Common collections you can loop over
| Model | Collections |
|---|---|
order |
order_lines |
order_line |
inventories, options, comments
|
shipment |
shipment_lines |
purchase_order |
purchase_order_items |
sales_order_return |
sales_order_return_items |
Loop vs quantifier vs accumulate
Three different things you might want to do with a collection:
-
Run an action on each item — use
for ... end. -
Ask a yes/no question about the collection — use a quantifier (
order has any|all|none ...). - Compute a sum/count/joined string across items — use accumulate.
Comments
Please sign in to leave a comment.