-
Notifications
You must be signed in to change notification settings - Fork 7
/
macro.rb
90 lines (69 loc) · 2.59 KB
/
macro.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
module Scrooge
module Optimizations
module Associations
module Macro
class << self
# Inject into ActiveRecord
#
def install!
unless scrooge_installed?
ActiveRecord::Base.send( :extend, SingletonMethods )
ActiveRecord::Associations::AssociationProxy.send( :include, InstanceMethods )
end
end
protected
def scrooge_installed?
ActiveRecord::Associations::AssociationProxy.included_modules.include?( InstanceMethods )
end
end
end
module SingletonMethods
@@preloadable_associations = {}
def self.extended( base )
eigen = class << base; self; end
end
def preload_scrooge_associations(result_set, callsite_sig)
scrooge_preloading_exclude do
callsite_associations = scrooge_callsite(callsite_sig).associations.to_a
preload_associations(result_set, callsite_associations)
end
end
def scrooge_preloading_exclude
unless Thread.current[:scrooge_preloading]
Thread.current[:scrooge_preloading] = true
yield
Thread.current[:scrooge_preloading] = false
end
end
# Let's not preload polymorphic associations or collections
#
def preloadable_associations
@@preloadable_associations[self.name] ||= reflect_on_all_associations.reject{|a| a.options[:polymorphic] || a.macro == :has_many }.map{|a| a.name }
end
end
module InstanceMethods
def self.included( base )
base.alias_method_chain :load_target, :scrooge
end
# note AssociationCollection has its own version of load_target, but we don't
# do collections at the moment anyway
#
def load_target_with_scrooge
scrooge_seen_association!(@reflection.name)
load_target_without_scrooge
end
private
# Register an association with Scrooge
#
def scrooge_seen_association!( association )
if @owner.scrooged? && !@loaded
@owner.class.scrooge_callsite(callsite_signature).association!(association)
end
end
def callsite_signature
@owner.instance_variable_get(:@attributes).callsite_signature
end
end
end
end
end