55
66module Panko ::Impl ::AttributesWriter ::ActiveRecord
77 class Writer
8+ def initialize
9+ @attributes_hash = EMPTY_HASH
10+ @attributes_hash_size = 0
11+ @indexed_row_column_indexes = nil
12+ @is_indexed_row = false
13+ @indexed_row_row = nil
14+ end
15+
816 def write_attributes ( object , descriptor , writer )
9- attributes_ctx = Context . new ( object )
17+ set_from_record ( object )
1018 object_class = object . class
1119
1220 length = descriptor . attributes . length
@@ -16,12 +24,92 @@ def write_attributes(object, descriptor, writer)
1624
1725 attribute . invalidate! ( object_class )
1826
19- value = attributes_ctx . read_attribute ( attribute )
27+ value = read_attribute ( attribute )
2028
2129 ValuesWriter . write ( writer , attribute , value )
2230
2331 i += 1
2432 end
2533 end
34+
35+ private
36+
37+ def set_from_record ( record )
38+ attributes_set = record . _panko_attributes
39+
40+ attributes_hash = attributes_set . _panko_attributes_hash
41+ if attributes_hash &.empty?
42+ @attributes_hash = EMPTY_HASH
43+ @attributes_hash_size = 0
44+ else
45+ @attributes_hash = attributes_hash
46+ @attributes_hash_size = attributes_hash . size
47+ end
48+
49+ @types = attributes_set . _panko_types
50+ @additional_types = attributes_set . _panko_additional_types
51+ @try_to_read_from_additional_types = !@additional_types . nil? && !@additional_types . empty?
52+
53+ @values = attributes_set . _panko_values
54+
55+ # Check if the values are of type ActiveRecord::Result::IndexedRow
56+ if PANKO_INDEX_ROW_DEFINED && @values . is_a? ( ActiveRecord ::Result ::IndexedRow )
57+ @indexed_row_column_indexes = @values . _panko_column_indexes
58+ @indexed_row_row = @values . _panko_row
59+ @is_indexed_row = true
60+ else
61+ @indexed_row_column_indexes = nil
62+ @is_indexed_row = false
63+ @indexed_row_row = nil
64+ end
65+ end
66+
67+ # Reads a value from the indexed row
68+ def read_value_from_indexed_row ( member )
69+ return nil if @indexed_row_column_indexes . nil? || @indexed_row_row . nil?
70+
71+ column_index = @indexed_row_column_indexes [ member ]
72+ return nil if column_index . nil?
73+
74+ row = @indexed_row_row
75+ return nil if row . nil?
76+
77+ row [ column_index ]
78+ end
79+
80+ # Reads the attribute value
81+ def read_attribute ( attribute )
82+ member = attribute . name
83+ value = nil
84+
85+ # If we have a populated attributes_hash
86+ if @attributes_hash_size > 0 && !@attributes_hash . nil?
87+ attribute_metadata = @attributes_hash [ member ]
88+ unless attribute_metadata . nil?
89+ value = attribute_metadata . instance_variable_get ( :@value_before_type_cast )
90+ attribute . type ||= attribute_metadata . instance_variable_get ( :@type )
91+ end
92+ end
93+
94+ # Fallback to reading from values or indexed row
95+ if value . nil? && !@values . nil?
96+ value = if @is_indexed_row
97+ read_value_from_indexed_row ( member )
98+ else
99+ @values [ member ]
100+ end
101+ end
102+
103+ # Fetch the type if not yet set
104+ if attribute . type . nil? && !value . nil?
105+ if @try_to_read_from_additional_types
106+ attribute . type = @additional_types [ member ]
107+ end
108+
109+ attribute . type ||= @types [ member ]
110+ end
111+
112+ value
113+ end
26114 end
27115end
0 commit comments