Skip to content

Commit 8e377f1

Browse files
author
Tom Smyth
committed
Added memoization of has_closure_tree_root
1 parent 4b69bf3 commit 8e377f1

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

lib/closure_tree/has_closure_tree_root.rb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,23 @@ def has_closure_tree_root(assoc_name, options = {})
1515
has_one assoc_name, -> { where(parent: nil) }, options
1616

1717
# Fetches the association, eager loading all children and given associations
18-
define_method("#{assoc_name}_including_tree") do |assoc_map = nil|
18+
define_method("#{assoc_name}_including_tree") do |assoc_map_or_reload = nil, assoc_map = nil|
19+
reload = false
20+
if assoc_map_or_reload.is_a?(::Hash)
21+
assoc_map = assoc_map_or_reload
22+
else
23+
reload = assoc_map_or_reload
24+
end
25+
26+
unless reload
27+
# Memoize
28+
@closure_tree_roots ||= {}
29+
@closure_tree_roots[assoc_name] ||= {}
30+
if @closure_tree_roots[assoc_name].has_key?(assoc_map)
31+
return @closure_tree_roots[assoc_name][assoc_map]
32+
end
33+
end
34+
1935
roots = options[:class_name].constantize.where(parent: nil, options[:foreign_key] => id).to_a
2036

2137
return nil if roots.empty?
@@ -65,7 +81,7 @@ def has_closure_tree_root(assoc_name, options = {})
6581
end
6682
end
6783

68-
root
84+
@closure_tree_roots[assoc_name][assoc_map] = root
6985
end
7086
end
7187
end

spec/has_closure_tree_root_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@
5050
end.to_not exceed_query_limit(4) # Without this feature, this is 15, and scales with number of nodes.
5151
end
5252

53+
it "memoizes by assoc_map" do
54+
group_reloaded.root_user_including_tree.email = "x"
55+
expect(group_reloaded.root_user_including_tree.email).to eq "x"
56+
group_reloaded.root_user_including_tree(contracts: :contract_type).email = "y"
57+
expect(group_reloaded.root_user_including_tree(contracts: :contract_type).email).to eq "y"
58+
expect(group_reloaded.root_user_including_tree.email).to eq "x"
59+
end
60+
61+
it "doesn't memoize if true argument passed" do
62+
group_reloaded.root_user_including_tree.email = "x"
63+
expect(group_reloaded.root_user_including_tree(true).email).to eq "1@example.com"
64+
group_reloaded.root_user_including_tree(contracts: :contract_type).email = "y"
65+
expect(group_reloaded.root_user_including_tree(true, contracts: :contract_type).email).
66+
to eq "1@example.com"
67+
end
68+
5369
it "eager loads inverse association to group" do
5470
expect do
5571
root = group_reloaded.root_user_including_tree

0 commit comments

Comments
 (0)