subroutine 4.0.1 → 4.1.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: c838c235e50f88722d2f39f19560fa5208a1e18f7cd0ee8edeeeea568e47166c
4
- data.tar.gz: 4bb808af75863ee0785ef8989b6ffc3423838dae84bb7a481d18aa759325c5be
3
+ metadata.gz: f8c6ad68f331c8b2d39a2667302f3306e7885bc9081d2d39ab4330cbcf16059b
4
+ data.tar.gz: 807815e357f3c06ecf7ae6949ff61521bac075fb946761196bc4b5fc6212ae27
5
5
  SHA512:
6
- metadata.gz: a008be5744be667696675df24ba4edf19a39716f27074ec192500ed30ba750d11974f1c3892144b13ff693631899cd0aa0931c5995b823ebe112073646fb5363
7
- data.tar.gz: f45212abc2f417d85c73db00ee83b9359ddc80d46fd77f78a45c802efe51a7374dcc978c0d7ded73ddd67c6637f252516c86abdf0f6f0ab309ef763476c17113
6
+ metadata.gz: 9980122e43941764e71e86d06f7bc2dd813b40ccc8577ab6383bf226c6da15be871f463d4662c984da22e03e3102ce23173d48b0c567272691dfc4dc6e44f278
7
+ data.tar.gz: 0dc35d0a0366e57bb44e6b6a1c972692e98ed983998e7df6b373aef7efbff6c060fea25b2d2f2e3a1cd90b35a0395f59e8a801b8065e9f3a52be14bcefd36c50
data/CHANGELOG.MD CHANGED
@@ -1,3 +1,16 @@
1
+ ## Subroutine 4.1.0
2
+
3
+ A field can no opt out of the natural assignment behavior of ActiveSupport::HashWithIndifferentAccess. Top level param groups are still accessible via indifferent access but if a field sets the `bypass_indifferent_assignment` option to `true` the HashWithIndifferentAccess assignment behavior will be bypassed in favor of direct Hash-like assignment.
4
+
5
+ ```ruby
6
+ class MyOp < Subroutine::Op
7
+
8
+ object :some_hash
9
+ object :some_other_hash, bypass_indifferent_assignment: true
10
+
11
+ end
12
+ ```
13
+
1
14
  ## Subroutine 4.0.1
2
15
 
3
16
  Association fields can now use `find_by()` instead of `find_by!()` by passing a `raise_on_miss: false` option. This places the responsibility on the op to manage nil cases rather than handling RecordNotFound errors.
@@ -5,7 +5,6 @@ module Subroutine
5
5
  class Configuration < ::SimpleDelegator
6
6
 
7
7
  PROTECTED_GROUP_IDENTIFIERS = %i[all original default].freeze
8
- INHERITABLE_OPTIONS = %i[mass_assignable field_reader field_writer groups aka].freeze
9
8
  NO_GROUPS = [].freeze
10
9
 
11
10
  def self.from(field_name, options)
@@ -61,7 +60,7 @@ module Subroutine
61
60
  end
62
61
 
63
62
  def inheritable_options
64
- config.slice(*INHERITABLE_OPTIONS)
63
+ config.slice(*Subroutine.inheritable_field_options)
65
64
  end
66
65
 
67
66
  def mass_assignable?
@@ -76,6 +75,10 @@ module Subroutine
76
75
  config[:field_reader] != false
77
76
  end
78
77
 
78
+ def bypass_indifferent_assignment?
79
+ config[:bypass_indifferent_assignment] == true
80
+ end
81
+
79
82
  def groups
80
83
  config[:groups] || NO_GROUPS
81
84
  end
@@ -186,7 +186,14 @@ module Subroutine
186
186
  end
187
187
 
188
188
  def set_param_group_value(name, key, value)
189
- get_param_group(name)[key.to_sym] = value
189
+ config = get_field_config(key)
190
+ group = get_param_group(name)
191
+
192
+ if config&.bypass_indifferent_assignment?
193
+ group.regular_writer(group.send(:convert_key, key), value)
194
+ else
195
+ group[key.to_sym] = value
196
+ end
190
197
  end
191
198
 
192
199
  def original_params
@@ -3,7 +3,7 @@
3
3
  module Subroutine
4
4
 
5
5
  MAJOR = 4
6
- MINOR = 0
6
+ MINOR = 1
7
7
  PATCH = 1
8
8
  PRE = nil
9
9
 
data/lib/subroutine.rb CHANGED
@@ -25,4 +25,13 @@ module Subroutine
25
25
  false
26
26
  end
27
27
 
28
+ def self.inheritable_field_options=(opts)
29
+ inheritable_field_options
30
+ @inheritable_field_options |= opts.map(&:to_sym)
31
+ end
32
+
33
+ def self.inheritable_field_options
34
+ @inheritable_field_options ||= %i[mass_assignable field_reader field_writer groups aka]
35
+ end
36
+
28
37
  end
@@ -175,6 +175,34 @@ module Subroutine
175
175
 
176
176
  op.object_input = { 'foo' => { 'bar' => :baz } }
177
177
  assert_equal({ 'foo' => { 'bar' => :baz } }, op.object_input)
178
+
179
+ op.object_input = { foo: "bar" }
180
+ assert op.object_input.is_a?(ActiveSupport::HashWithIndifferentAccess)
181
+ end
182
+
183
+ def test_hash_inputs_can_opt_out_of_indifferent_access_behavior
184
+ op.no_indifferent_object_input = nil
185
+ assert_nil op.no_indifferent_object_input
186
+
187
+ op.no_indifferent_object_input = ''
188
+ assert_equal({}, op.no_indifferent_object_input)
189
+
190
+ op.no_indifferent_object_input = [[:a, :b]]
191
+ assert_equal({ a: :b }, op.no_indifferent_object_input)
192
+
193
+ op.no_indifferent_object_input = { foo: "bar" }
194
+ assert_equal({ foo: "bar" }, op.no_indifferent_object_input)
195
+ assert op.no_indifferent_object_input.key?(:foo)
196
+ refute op.no_indifferent_object_input.key?("foo")
197
+ refute op.no_indifferent_object_input.is_a?(ActiveSupport::HashWithIndifferentAccess)
198
+ assert op.no_indifferent_object_input.is_a?(Hash)
199
+
200
+ op.no_indifferent_object_input = { "foo" => "bar" }
201
+ assert_equal({ "foo" => "bar" }, op.no_indifferent_object_input)
202
+ assert op.no_indifferent_object_input.key?("foo")
203
+ refute op.no_indifferent_object_input.key?(:foo)
204
+ refute op.no_indifferent_object_input.is_a?(ActiveSupport::HashWithIndifferentAccess)
205
+ assert op.no_indifferent_object_input.is_a?(Hash)
178
206
  end
179
207
 
180
208
  def test_array_inputs
data/test/support/ops.rb CHANGED
@@ -176,6 +176,7 @@ class TypeCastOp < ::Subroutine::Op
176
176
  iso_date :iso_date_input
177
177
  iso_time :iso_time_input
178
178
  object :object_input
179
+ object :no_indifferent_object_input, bypass_indifferent_assignment: true
179
180
  array :array_input, default: "foo"
180
181
  array :type_array_input, of: :integer
181
182
  file :file_input
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: subroutine
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Nelson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-17 00:00:00.000000000 Z
11
+ date: 2024-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel