@spree/docs 0.1.168 → 0.1.169
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -384,10 +384,121 @@ The `compare_at_price` **reader** (which resolves against `cost_currency`) is un
|
|
|
384
384
|
Also note:
|
|
385
385
|
|
|
386
386
|
- **Ransack:** `default_price` is no longer a searchable association on `Variant`; query `prices` instead.
|
|
387
|
-
-
|
|
387
|
+
- **Prices in permitted params:** the dead `:price` and `:compare_at_price` entries are gone. Prices were already written as nested `prices: [{ amount:, currency: }]` under variants — the top-level keys had no writer behind them. (`Spree::PermittedAttributes` itself is removed in 6.0 — see below.)
|
|
388
388
|
- Localized number parsing still happens: `Spree::Price#amount=` runs `Spree::LocalizedNumber.parse`, so `set_price(currency, '1,599.99')` works as `price=` did.
|
|
389
389
|
- The variant validation that inferred a missing price from the product's default variant is gone. Set prices explicitly (the product and variant factories already do).
|
|
390
390
|
|
|
391
|
+
### `Spree::PermittedAttributes` is removed
|
|
392
|
+
|
|
393
|
+
The global permitted-attributes registry is gone, with no deprecation bridge. It
|
|
394
|
+
existed so the Rails admin and storefront could share one allowlist; both are
|
|
395
|
+
removed in 6.0, and API v3 declares its attributes in the controller.
|
|
396
|
+
|
|
397
|
+
Removed alongside it: `Spree::Core::ControllerHelpers::StrongParameters` (the
|
|
398
|
+
`permitted_*_attributes` helper methods it mixed into controllers) and the
|
|
399
|
+
fallback that inferred an attribute list from the model name.
|
|
400
|
+
|
|
401
|
+
Attributes you pushed from an initializer are now declared on the model, and
|
|
402
|
+
standard resource endpoints append them to their own allowlist — so one
|
|
403
|
+
declaration still covers the model's create and update endpoints.
|
|
404
|
+
|
|
405
|
+
#### How to migrate
|
|
406
|
+
|
|
407
|
+
**1. Find every call site.** The constant and the helper methods are both gone,
|
|
408
|
+
so a missed reference raises `NameError` or `NoMethodError` the first time that
|
|
409
|
+
code runs — loudly, but not necessarily at boot:
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
grep -rn "PermittedAttributes" app config lib
|
|
413
|
+
grep -rnE "permitted_[[:alnum:]_]+_attributes" app config lib
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
The second pattern is deliberately broad: the helper module generated one
|
|
417
|
+
`permitted_*_attributes` method per registry key, so there were dozens of them.
|
|
418
|
+
|
|
419
|
+
**2. Decide what each attribute actually is.** Most fall into one of three
|
|
420
|
+
buckets, and only the last needs this hook:
|
|
421
|
+
|
|
422
|
+
| What you were adding | Where it goes in 6.0 |
|
|
423
|
+
| --- | --- |
|
|
424
|
+
| A merchant-managed field (text, number, dropdown) | [Custom Fields](../core-concepts/custom-fields.md) — no code, and filterable/sortable |
|
|
425
|
+
| Config for an STI type you register (promotion rule, delivery method rule, …) | `additional_permitted_attributes` on that subclass, as before — unchanged |
|
|
426
|
+
| A real database column your extension added to a core model | `additional_permitted_attributes` on the model |
|
|
427
|
+
|
|
428
|
+
**3. Point each declaration at the model.** It stays in your initializer — only
|
|
429
|
+
the receiver changes, from the global registry to the model itself:
|
|
430
|
+
|
|
431
|
+
```ruby config/initializers/spree.rb
|
|
432
|
+
# Before
|
|
433
|
+
Spree::PermittedAttributes.product_attributes << :brand_id
|
|
434
|
+
|
|
435
|
+
# After
|
|
436
|
+
Spree::Product.additional_permitted_attributes += [:brand_id]
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
Use `+=`, not `=` — the list is per model, and assigning replaces whatever
|
|
440
|
+
another extension already added. `<<` raises a `FrozenError`: the default is a
|
|
441
|
+
frozen shared array, so mutating it in place would leak your attribute onto every
|
|
442
|
+
other model.
|
|
443
|
+
|
|
444
|
+
Declare only attributes of your own. Redeclaring a key the controller already
|
|
445
|
+
permits (`metadata`, `prices`) does not widen it — strong parameters keeps the
|
|
446
|
+
last filter for that key, so the controller's own would be replaced by yours.
|
|
447
|
+
|
|
448
|
+
Entries are `params.permit` fragments, so collections and nested structures keep
|
|
449
|
+
the shapes you already know: `[:brand_id, { region_ids: [] }]`.
|
|
450
|
+
|
|
451
|
+
**4. Fix your own controllers.** If you subclassed a Spree v3 resource
|
|
452
|
+
controller and relied on the attribute list being inferred from the model name,
|
|
453
|
+
declare it now:
|
|
454
|
+
|
|
455
|
+
```ruby
|
|
456
|
+
class BrandsController < Spree::Api::V3::Admin::ResourceController
|
|
457
|
+
protected
|
|
458
|
+
|
|
459
|
+
def model_class
|
|
460
|
+
Spree::Brand
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
# Before: no such method — the base class inferred `brand_attributes`
|
|
464
|
+
# from the model name. Now you say what you accept.
|
|
465
|
+
def resource_permitted_attributes
|
|
466
|
+
[:name, :slug, :description]
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
Declaring neither `resource_permitted_attributes` nor `permitted_params` raises
|
|
472
|
+
`NotImplementedError` on the first write, so this surfaces in your test suite
|
|
473
|
+
rather than silently permitting a stale list.
|
|
474
|
+
|
|
475
|
+
**5. Verify a write actually persists.** A declaration that never reaches a
|
|
476
|
+
controller fails silently — strong parameters drop the unpermitted key, the
|
|
477
|
+
request still returns 200, and the column keeps its old value. Assert on the
|
|
478
|
+
saved record, not the response status:
|
|
479
|
+
|
|
480
|
+
```ruby
|
|
481
|
+
patch "/api/v3/admin/products/#{product.prefixed_id}",
|
|
482
|
+
params: { brand_id: brand.id }, headers: headers
|
|
483
|
+
|
|
484
|
+
expect(product.reload.brand_id).to eq(brand.id)
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
If that assertion fails, the endpoint is not consulting your declaration. Check
|
|
488
|
+
whether the controller overrides `permitted_attributes` — that method is where
|
|
489
|
+
the extension attributes are appended, so overriding it replaces them. Override
|
|
490
|
+
`resource_permitted_attributes` instead.
|
|
491
|
+
|
|
492
|
+
> **WARNING:** Two endpoints deliberately ignore the hook because their parameters are
|
|
493
|
+
> authorization data rather than resource data: API keys (`scopes`, `key_type`)
|
|
494
|
+
> and invitations (`role_id`). Adding attributes there needs a controller
|
|
495
|
+
> decorator, not a model declaration.
|
|
496
|
+
|
|
497
|
+
STI types registered through a Spree registry (promotion rules and actions,
|
|
498
|
+
delivery method rules, commission rules) already used
|
|
499
|
+
`additional_permitted_attributes` and need no changes — the hook simply moved up
|
|
500
|
+
to `Spree::Base`.
|
|
501
|
+
|
|
391
502
|
### `StateChange` and `LogEntry` are gone
|
|
392
503
|
|
|
393
504
|
`Spree::StateChange` and `Spree::LogEntry` are removed — the models, the `state_changes` associations on `Order`, `Payment` and `Fulfillment`, the `log_entries` associations on `Payment` and `Refund`, and everything that wrote to them. Both were write-only: nothing in Spree read the rows back, and the admin screens that displayed them are gone.
|