permittable 0.5.0 → 0.5.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/permittable/version.rb +1 -1
- data/lib/permittable.rb +10 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d9b826995301bd0dc72ab69a6560ddfe58e13ae67323a252a9a506c21f61420d
|
|
4
|
+
data.tar.gz: 5e354c9e104237d9116591df08d4c1a58962f98d543d0f5ff6de983b96f3bc51
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c9cf62a2210a42cad9190f25ce259250c268dabf72bb966bae4110d2c627f27ce7a050a64f92c9e1729c9eb088d48077384b901481475a5cae077d1d802684ab
|
|
7
|
+
data.tar.gz: a6db0156d761c972ef0c9f6b41ef96e3fee3f0f48158ce01344b8a6ea39f9a8504dd2df015bcf3c379841420a66e857a42a2d0ff07d2d94902b49d89fec6b570
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
<!-- CHANGELOG.md -->
|
|
2
2
|
|
|
3
|
+
## 0.5.1 (2026-09-02)
|
|
4
|
+
<!-- title: nested input outside Rails -->
|
|
5
|
+
|
|
6
|
+
Patch release. Checking how a contract handles a request with several top-level envelopes (`{ user: { ... }, address_attributes: { ... } }`) surfaced one crash and one unhelpful error; both are fixed below, and no behaviour of existing contracts changes.
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
- **Nested hash input crashed outside Rails.** `lib/permittable.rb` required `HashWithIndifferentAccess` but not the Hash core extension it needs to convert nested plain Hashes, so a standalone `Permittable::Contract` (or any host that loads only `permittable`) raised `NoMethodError: undefined method 'nested_under_indifferent_access'` on payloads like `{ user: { ... }, address_attributes: { ... } }`. Rails apps and the spec suite loaded the extension indirectly, which is why it went unnoticed; a spec now exercises a nested contract in a bare subprocess.
|
|
10
|
+
- **`root:` rejects anything but one key at class load.** `root: [:user, :address_attributes]` used to leak `NoMethodError: undefined method 'to_sym' for Array`; it now raises a descriptive `ArgumentError` pointing at the recipe for several top-level envelopes — a rootless contract with one nested block per key. Specs pin that recipe, and pin that a rooted contract never sees the root's siblings (even under `unknown: :error`), matching `require(:user).permit`.
|
|
11
|
+
|
|
3
12
|
## 0.5.0 (2026-09-02)
|
|
4
13
|
<!-- title: the adoption on-ramp -->
|
|
5
14
|
|
data/lib/permittable/version.rb
CHANGED
data/lib/permittable.rb
CHANGED
|
@@ -2,6 +2,7 @@ require "active_support"
|
|
|
2
2
|
require "active_support/concern"
|
|
3
3
|
require "active_support/notifications"
|
|
4
4
|
require "active_support/hash_with_indifferent_access"
|
|
5
|
+
require "active_support/core_ext/hash/indifferent_access" # nested plain Hashes inside HWIA.new
|
|
5
6
|
require "active_support/core_ext/class/attribute"
|
|
6
7
|
require "active_support/core_ext/string/inflections"
|
|
7
8
|
require "active_support/core_ext/string/filters"
|
|
@@ -611,6 +612,10 @@ module Permittable
|
|
|
611
612
|
#
|
|
612
613
|
# root: key to unwrap first (`require(:user)` equivalent); false
|
|
613
614
|
# (default) reads top-level params. Missing root renders 400.
|
|
615
|
+
# Exactly one key: a rooted contract never sees the root's
|
|
616
|
+
# siblings (like `require(:user).permit`), so to accept
|
|
617
|
+
# several top-level envelopes stay rootless and declare one
|
|
618
|
+
# nested block per key.
|
|
614
619
|
# model: a model class (or `true` to infer from controller_name)
|
|
615
620
|
# enabling the schema-drift check on every non-virtual scalar
|
|
616
621
|
# field.
|
|
@@ -627,6 +632,11 @@ module Permittable
|
|
|
627
632
|
def permit_params(*actions, root: false, model: nil, unknown: :ignore, enforce: false, mode: nil, desc: nil, &block)
|
|
628
633
|
raise ArgumentError, "#{LABEL}: permit_params requires a block declaring the contract fields" unless block
|
|
629
634
|
|
|
635
|
+
unless root.nil? || root == false || root.is_a?(Symbol) || root.is_a?(String)
|
|
636
|
+
raise ArgumentError, "#{LABEL}: :root must be one key (Symbol or String) or false, got #{root.inspect} — " \
|
|
637
|
+
"to accept several top-level keys, declare a rootless contract with one nested block per key"
|
|
638
|
+
end
|
|
639
|
+
|
|
630
640
|
unknown = unknown.to_sym
|
|
631
641
|
raise ArgumentError, "#{LABEL}: :unknown must be one of #{UNKNOWN_MODES.join(', ')}" unless UNKNOWN_MODES.include?(unknown)
|
|
632
642
|
|