structure 3.1.1 → 3.3.0

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: 91e04b84b8e6a19728bf6212bdfd08895187bbe59ebf56b47288697962ed31b2
4
- data.tar.gz: '028e8df792d344faa2850f82504d223a6691c195203c51acd53581ee9e97064c'
3
+ metadata.gz: 69bf1e759bbf993b28fb70235866a6c36774b92a57ee47764458d24bb062a55b
4
+ data.tar.gz: 3e9a55913e14fb630ece6c4fff62df1d8bfff69d61efd1034a406cf404423f96
5
5
  SHA512:
6
- metadata.gz: 4e6fbbd3104fc0ed9001d66395606ab436a907cf3b1ab09f692c458b99e999e648e7b558dd0b2e8e4fb298d2c1c25decf51bef0ad5889bc9ff14f6d821c62ede
7
- data.tar.gz: 74752c31b2898fea6c7d5c94e568f7fa9ca2724e116aa62e9d9c30f0da77d3f6f7de7b73540a8837834536bc2aa9b87f9d5b596ddd0bfd2089222e3fbec07334
6
+ metadata.gz: c8b75ee56372f7af3ffd9398474ce25bcffed641314a77293a735cc5e5269f68ee7ba645ed44456eea5c84d1c2b551d0181be35519a61b553466ceda85287f8a
7
+ data.tar.gz: 3f736db422a6abe5dae0b59d37194d8f2242c2970a506f40efe04b379f00b7cbc14dd2a3437023d0a33bd0d80376f6418c1421659d446c546d56ccbb1352abf5
@@ -65,7 +65,7 @@ module Structure
65
65
 
66
66
  def predicate_methods
67
67
  @types.filter_map do |name, type_lambda|
68
- if type_lambda == Types.boolean && !name.to_s.end_with?("?")
68
+ if Types.boolean?(type_lambda) && !name.to_s.end_with?("?")
69
69
  predicate_name = "#{name}?"
70
70
  [predicate_name.to_sym, name]
71
71
  end
@@ -10,8 +10,8 @@ module Structure
10
10
  BOOLEAN_TRUTHY = [true, 1, "1", "t", "T", "true", "TRUE", "on", "ON"].freeze
11
11
  private_constant :BOOLEAN_TRUTHY
12
12
 
13
- def boolean
14
- @boolean ||= ->(val) { BOOLEAN_TRUTHY.include?(val) }
13
+ def boolean?(type)
14
+ type == boolean
15
15
  end
16
16
 
17
17
  # Main factory method for creating type coercers
@@ -34,14 +34,8 @@ module Structure
34
34
  case type
35
35
  when :boolean
36
36
  boolean
37
- when Class, Module
38
- if type.name && Kernel.respond_to?(type.name)
39
- kernel(type)
40
- elsif type.respond_to?(:parse)
41
- parseable(type)
42
- else
43
- type
44
- end
37
+ when :self
38
+ self_referential
45
39
  when Array
46
40
  if type.length == 1
47
41
  array(type.first)
@@ -49,12 +43,27 @@ module Structure
49
43
  type
50
44
  end
51
45
  else
52
- type
46
+ # Handle Class, Module, and any other types
47
+ if type.respond_to?(:parse)
48
+ parseable(type)
49
+ elsif type.respond_to?(:name) && type.name && Kernel.respond_to?(type.name)
50
+ kernel(type)
51
+ else
52
+ type
53
+ end
53
54
  end
54
55
  end
55
56
 
56
57
  private
57
58
 
59
+ def boolean
60
+ @boolean ||= ->(val) { BOOLEAN_TRUTHY.include?(val) }
61
+ end
62
+
63
+ def self_referential
64
+ proc { |val| parse(val) }
65
+ end
66
+
58
67
  def kernel(type)
59
68
  ->(val) { Kernel.send(type.name, val) }
60
69
  end
@@ -64,8 +73,12 @@ module Structure
64
73
  end
65
74
 
66
75
  def array(element_type)
67
- element_coercer = coerce(element_type)
68
- ->(array) { array.map { |element| element_coercer.call(element) } }
76
+ if element_type == :self
77
+ proc { |array| array.map { |element| parse(element) } }
78
+ else
79
+ element_coercer = coerce(element_type)
80
+ ->(array) { array.map { |element| element_coercer.call(element) } }
81
+ end
69
82
  end
70
83
  end
71
84
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Structure
4
- VERSION = "3.1.1"
4
+ VERSION = "3.3.0"
5
5
  end
data/lib/structure.rb CHANGED
@@ -39,6 +39,25 @@ module Structure
39
39
  attributes = builder.attributes
40
40
  after_parse_callback = builder.after_parse_callback
41
41
 
42
+ # Override to_h to recursively convert nested objects with to_h
43
+ data_class.define_method(:to_h) do
44
+ result = {}
45
+ self.class.members.each do |member|
46
+ value = send(member)
47
+ result[member] = case value
48
+ when Array
49
+ value.map { |item| item.respond_to?(:to_h) && item ? item.to_h : item }
50
+ when Hash
51
+ value
52
+ when ->(v) { v.respond_to?(:to_h) && v }
53
+ value.to_h
54
+ else
55
+ value
56
+ end
57
+ end
58
+ result
59
+ end
60
+
42
61
  data_class.define_singleton_method(:parse) do |data = {}, **kwargs|
43
62
  # Merge kwargs into data - kwargs take priority as overrides
44
63
  # Convert kwargs symbol keys to strings to match source_key lookups
@@ -58,7 +77,13 @@ module Structure
58
77
 
59
78
  # Apply type coercion or transformation
60
79
  if types[attr] && !value.nil?
61
- value = types[attr].call(value)
80
+ type_or_proc = types[attr]
81
+ # Use instance_exec for non-lambda procs (self-referential types)
82
+ value = if type_or_proc.is_a?(Proc) && !type_or_proc.lambda?
83
+ instance_exec(value, &type_or_proc)
84
+ else
85
+ type_or_proc.call(value)
86
+ end
62
87
  end
63
88
 
64
89
  final_kwargs[attr] = value
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: structure
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hakan Ensari