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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59d816740d54375ea14045959a2afb70dffee709e21350b914d69fcc115655c4
4
- data.tar.gz: 233c21f86657a7643c5a8de70b83001e8f66b5e0ad3d1ae71e25a79b22883753
3
+ metadata.gz: d9b826995301bd0dc72ab69a6560ddfe58e13ae67323a252a9a506c21f61420d
4
+ data.tar.gz: 5e354c9e104237d9116591df08d4c1a58962f98d543d0f5ff6de983b96f3bc51
5
5
  SHA512:
6
- metadata.gz: 249dfeaf789c471b84589e5e49ee70148774fb03a5eaa3906a479088f7da68bc6d3f8a9b8d513e19c9f1fba18a62be1a6d9a68d1390b96c22c906e1ae208f002
7
- data.tar.gz: a17c6c12cf879384624cd4f1eb654a05fc9cb5e641d821ee99461d459156744eb372bd51ced705588c6af7a5f2f713ee8285fb9f1c38a7eb42f2aaf6667a5867
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
 
@@ -1,3 +1,3 @@
1
1
  module Permittable
2
- VERSION = "0.5.0".freeze
2
+ VERSION = "0.5.1".freeze
3
3
  end
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
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: permittable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ethan Nguyen