subroutine 4.0.1 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
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