@@ -2,11 +2,10 @@ module ActiveRecord
2
2
3
3
module ClassMethods
4
4
5
- def inherited ( subclass )
6
- [ '_attribute_aliases' ] . each do |inheritable_attribute |
7
- instance_var = "@#{ inheritable_attribute } "
8
- subclass . instance_variable_set ( instance_var , instance_variable_get ( instance_var ) )
9
- end
5
+ alias _new_without_sti_type_cast new
6
+
7
+ def new ( *args , &block )
8
+ _new_without_sti_type_cast ( *args , &block ) . cast_to_current_sti_type
10
9
end
11
10
12
11
def base_class
@@ -16,10 +15,8 @@ def base_class
16
15
17
16
if superclass == Base || superclass . abstract_class?
18
17
self
19
- elsif respond_to? ( :each )
20
- superclass . base_class
21
18
else
22
- self
19
+ superclass . base_class
23
20
end
24
21
end
25
22
@@ -28,19 +25,26 @@ def abstract_class?
28
25
end
29
26
30
27
def primary_key
31
- base_class . instance_eval { @primary_key_value || :id }
28
+ @primary_key_value ||= ( self == base_class ) ? :id : base_class . primary_key
32
29
end
33
30
34
31
def primary_key = ( val )
35
- base_class . instance_eval { @primary_key_value = val }
32
+ @primary_key_value = val . to_s
36
33
end
37
34
38
35
def inheritance_column
39
- base_class . instance_eval { @inheritance_column_value || "type" }
36
+ return nil if @no_inheritance_column
37
+ @inheritance_column_value ||=
38
+ if self == base_class
39
+ @inheritance_column_value || 'type'
40
+ else
41
+ superclass . inheritance_column . tap { |v | @no_inheritance_column = !v }
42
+ end
40
43
end
41
44
42
45
def inheritance_column = ( name )
43
- base_class . instance_eval { @inheritance_column_value = name }
46
+ @no_inheritance_column = !name
47
+ @inheritance_column_value = name
44
48
end
45
49
46
50
def model_name
@@ -49,15 +53,11 @@ def model_name
49
53
end
50
54
51
55
def find ( id )
52
- klass = self
53
- base_class . instance_eval { ReactiveRecord ::Base . find ( klass , primary_key , id ) }
56
+ ReactiveRecord ::Base . find ( self , primary_key , id )
54
57
end
55
58
56
59
def find_by ( opts = { } )
57
- klass = self
58
- base_class . instance_eval do
59
- ReactiveRecord ::Base . find ( klass , _dealias_attribute ( opts . first . first ) , opts . first . last )
60
- end
60
+ ReactiveRecord ::Base . find ( self , _dealias_attribute ( opts . first . first ) , opts . first . last )
61
61
end
62
62
63
63
def enum ( *args )
@@ -69,7 +69,11 @@ def serialize(attr, *args)
69
69
end
70
70
71
71
def _dealias_attribute ( new )
72
- _attribute_aliases [ new ] || new
72
+ if self == base_class
73
+ _attribute_aliases [ new ] || new
74
+ else
75
+ _attribute_aliases [ new ] ||= superclass . _dealias_attribute ( new )
76
+ end
73
77
end
74
78
75
79
def _attribute_aliases
@@ -80,7 +84,7 @@ def alias_attribute(new_name, old_name)
80
84
[ '' , '=' , '_changed?' ] . each do |variant |
81
85
define_method ( "#{ new_name } #{ variant } " ) { |*args , &block | send ( "#{ old_name } #{ variant } " , *args , &block ) }
82
86
end
83
- _attribute_aliases [ new_name ] = old_name
87
+ @ _attribute_aliases[ new_name ] = old_name
84
88
end
85
89
86
90
# ignore any of these methods if they get called on the client. This list should be trimmed down to include only
@@ -222,15 +226,43 @@ def default_scope(*args, &block)
222
226
def all
223
227
ReactiveRecord ::Base . default_scope [ self ] ||=
224
228
begin
229
+ puts "defining all for #{ self } "
225
230
root = ReactiveRecord ::Collection
226
231
. new ( self , nil , nil , self , 'all' )
227
232
. extend ( ReactiveRecord ::UnscopedCollection )
228
- ( @_default_scopes || [ { client : -> ( ) { true } } ] ) . inject ( root ) do |scope , opts |
233
+ ( @_default_scopes || [ { client : _all_filter } ] ) . inject ( root ) do |scope , opts |
229
234
scope . build_child_scope ( ReactiveRecord ::ScopeDescription . new ( self , :all , opts ) )
230
235
end
231
236
end
232
237
end
233
238
239
+ def _all_filter
240
+ # provides a filter for the all scopes taking into account STI subclasses
241
+ # note: within the lambda `self` will be the model instance
242
+ defining_class_is_base_class = base_class == self
243
+ defining_model_name = model_name
244
+ lambda do
245
+ # have to delay computation of inheritance column since it might
246
+ # not be defined when class is first defined
247
+ ic = self . class . inheritance_column
248
+ ( defining_class_is_base_class || !ic || self [ ic ] == defining_model_name ) . tap do |x |
249
+ puts "_all_filter(#{ self } ) returns: #{ x } defining_model_name: #{ defining_model_name } , is base: #{ defining_class_is_base_class } , ic: #{ ic } , self[ic]: #{ self [ ic ] } "
250
+ end
251
+ end
252
+ #
253
+ # if base_class == self || !inheritance_column
254
+ # puts "creating a base filter: #{model_name} #{base_class} #{self} #{inheritance_column}"
255
+ # # always return true for the base_class (or if there is no inheritance column)
256
+ # -> () { puts "#{model_name} #{self.class.base_class} #{self.class} #{self.class.inheritance_column} base all filter"; true }
257
+ # else
258
+ # # otherwise we are in a STI subclass so inheritance column name must match model name
259
+ # # optimize by capturing the inheritance column and model_name as local vars
260
+ # klass_inheritance_column = inheritance_column
261
+ # klass_model_name = model_name
262
+ # -> () { puts "subclass all filter #{klass_inheritance_column} #{klass_model_name} #{self[klass_inheritance_column] == klass_model_name}"; self[klass_inheritance_column] == klass_model_name }
263
+ # end
264
+ end
265
+
234
266
# def all=(_collection)
235
267
# raise "NO LONGER IMPLEMENTED DOESNT PLAY WELL WITH SYNCHROMESH"
236
268
# end
@@ -333,6 +365,7 @@ def define_attribute_methods
333
365
define_method ( "#{ name } _changed?" ) { @backing_record . changed? ( name ) }
334
366
define_method ( "#{ name } ?" ) { @backing_record . get_attr_value ( name , nil ) . present? }
335
367
end
368
+ self . inheritance_column = nil if inheritance_column && !columns_hash . key? ( inheritance_column )
336
369
end
337
370
338
371
def _react_param_conversion ( param , opt = nil )
0 commit comments