@@ -67,30 +67,35 @@ def self.load_from_json(json, target = nil)
67
67
load_data { ServerDataCache . load_from_json ( json , target ) }
68
68
end
69
69
70
+ def self . find_locally ( model , attrs , new_only : nil )
71
+ if ( id_to_find = attrs [ model . primary_key ] )
72
+ !new_only && lookup_by_id ( model , id_to_find )
73
+ else
74
+ @records [ model ] . detect do |r |
75
+ ( r . new? || !new_only ) &&
76
+ !attrs . detect { |attr , value | r . synced_attributes [ attr ] != value }
77
+ end
78
+ end
79
+ end
80
+
81
+ def self . find_by_id ( model , id )
82
+ find ( model , model . primary_key => id )
83
+ end
84
+
70
85
def self . find ( model , attrs )
71
86
# will return the unique record with this attribute-value pair
72
87
# value cannot be an association or aggregation
73
88
74
89
# add the inheritance column if this is an STI subclass
75
90
76
- inher_col = model . inheritance_column
77
- if inher_col && model < model . base_class && !attrs . key? ( inher_col )
78
- attrs = attrs . merge ( inher_col => model . model_name . to_s )
79
- end
91
+ attrs = model . __hyperstack_preprocess_attrs ( attrs )
80
92
81
93
model = model . base_class
82
94
primary_key = model . primary_key
83
95
84
96
# already have a record with these attribute-value pairs?
85
97
86
- record =
87
- if ( id_to_find = attrs [ primary_key ] )
88
- lookup_by_id ( model , id_to_find )
89
- else
90
- @records [ model ] . detect do |r |
91
- !attrs . detect { |attr , value | r . synced_attributes [ attr ] != value }
92
- end
93
- end
98
+ record = find_locally ( model , attrs )
94
99
95
100
unless record
96
101
# if not, and then the record may be loaded, but not have this attribute set yet,
@@ -102,10 +107,8 @@ def self.find(model, attrs)
102
107
attrs = attrs . merge primary_key => id
103
108
end
104
109
# if we don't have a record then create one
105
- # (record = new(model)).vector = [model, [:find_by, attribute => value]] unless record
106
- record ||= set_vector_lookup ( new ( model ) , [ model , [ :find_by , attrs ] ] )
107
- # and set the values
108
- attrs . each { |attr , value | record . sync_attribute ( attr , value ) }
110
+ record ||= set_vector_lookup ( new ( model ) , [ model , *find_by_vector ( attrs ) ] )
111
+ record . sync_attributes ( attrs )
109
112
end
110
113
# finally initialize and return the ar_instance
111
114
record . set_ar_instance!
@@ -122,7 +125,6 @@ def self.new_from_vector(model, aggregate_owner, *vector)
122
125
# record = @records[model].detect { |record| record.vector == vector }
123
126
record = lookup_by_vector ( vector )
124
127
unless record
125
-
126
128
record = new model
127
129
set_vector_lookup ( record , vector )
128
130
end
@@ -175,6 +177,7 @@ def id=(value)
175
177
@ar_instance . instance_variable_set ( :@backing_record , existing_record )
176
178
existing_record . attributes . merge! ( attributes ) { |key , v1 , v2 | v1 }
177
179
end
180
+ @id = value
178
181
value
179
182
end
180
183
@@ -211,7 +214,7 @@ def errors
211
214
212
215
def initialize_collections
213
216
if ( !vector || vector . empty? ) && id && id != ''
214
- Base . set_vector_lookup ( self , [ @model , [ :find_by , @model . primary_key => id ] ] )
217
+ Base . set_vector_lookup ( self , [ @model , * find_by_vector ( @model . primary_key => id ) ] )
215
218
end
216
219
Base . load_data do
217
220
@model . reflect_on_all_associations . each do |assoc |
@@ -251,16 +254,20 @@ def sync_unscoped_collection!
251
254
@synced_with_unscoped = !@synced_with_unscoped
252
255
end
253
256
254
- def sync_attribute ( attribute , value )
257
+ def sync_attributes ( attrs )
258
+ attrs . each { |attr , value | sync_attribute ( attr , value ) }
259
+ self
260
+ end
255
261
262
+ def sync_attribute ( attribute , value )
256
263
@synced_attributes [ attribute ] = @attributes [ attribute ] = value
257
264
Base . set_id_lookup ( self ) if attribute == primary_key
258
265
259
266
#@synced_attributes[attribute] = value.dup if value.is_a? ReactiveRecord::Collection
260
267
261
268
if value . is_a? Collection
262
269
@synced_attributes [ attribute ] = value . dup_for_sync
263
- elsif aggregation = model . reflect_on_aggregation ( attribute ) and ( aggregation . klass < ActiveRecord ::Base )
270
+ elsif ( aggregation = model . reflect_on_aggregation ( attribute ) ) && ( aggregation . klass < ActiveRecord ::Base )
264
271
value . backing_record . sync!
265
272
elsif aggregation
266
273
@synced_attributes [ attribute ] = aggregation . deserialize ( aggregation . serialize ( value ) )
@@ -278,6 +285,14 @@ def self.exists?(model, id)
278
285
Base . lookup_by_id ( model , id )
279
286
end
280
287
288
+ def id_loaded?
289
+ @id
290
+ end
291
+
292
+ def loaded_id = ( id )
293
+ @id = id
294
+ end
295
+
281
296
def revert
282
297
@changed_attributes . dup . each do |attribute |
283
298
@ar_instance . send ( "#{ attribute } =" , @synced_attributes [ attribute ] )
0 commit comments